<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.9.4"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Flow-IPC: ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt; Class Template Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr id="projectrow">
  <td id="projectalign">
   <div id="projectname">Flow-IPC<span id="projectnumber">&#160;1.0.2</span>
   </div>
   <div id="projectbrief">Flow-IPC project: Full implementation reference.</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.4 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search",'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="namespaceipc.html">ipc</a></li><li class="navelem"><a class="el" href="namespaceipc_1_1transport.html">transport</a></li><li class="navelem"><a class="el" href="namespaceipc_1_1transport_1_1struc.html">struc</a></li><li class="navelem"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">Channel</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="summary">
<a href="#nested-classes">Classes</a> &#124;
<a href="#pub-types">Public Types</a> &#124;
<a href="#pub-methods">Public Member Functions</a> &#124;
<a href="#pub-static-methods">Static Public Member Functions</a> &#124;
<a href="#pri-types">Private Types</a> &#124;
<a href="#pri-methods">Private Member Functions</a> &#124;
<a href="#pri-attribs">Private Attributes</a> &#124;
<a href="#related">Related Functions</a> &#124;
<a href="classipc_1_1transport_1_1struc_1_1Channel-members.html">List of all members</a>  </div>
  <div class="headertitle"><div class="title">ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt; Class Template Reference</div></div>
</div><!--header-->
<div class="contents">

<p>Owning and wrapping a pre-connected <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> peer (an endpoint of an established channel over which <em>unstructured</em> messages and optionally native handles can be transported), this template is the central pillar of the <a class="el" href="namespaceipc_1_1transport_1_1struc.html" title="Sub-module of Flow-IPC module ipc::transport providing transmission of structured messages specifical...">ipc::transport::struc</a> (<em>structured layer</em>), capable of communicating structured capnp-schema-based messages (and native handles).  
 <a href="classipc_1_1transport_1_1struc_1_1Channel.html#details">More...</a></p>

<p><code>#include &lt;<a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>&gt;</code></p>
<div class="dynheader">
Inheritance diagram for ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classipc_1_1transport_1_1struc_1_1Channel__inherit__graph.svg" width="310" height="143"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
<center><span class="legend">[<a href="graph_legend.html">legend</a>]</span></center></div>
<div class="dynheader">
Collaboration diagram for ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classipc_1_1transport_1_1struc_1_1Channel__coll__graph.svg" width="538" height="432"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
<center><span class="legend">[<a href="graph_legend.html">legend</a>]</span></center></div>
<table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="nested-classes" name="nested-classes"></a>
Classes</h2></td></tr>
<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="structipc_1_1transport_1_1struc_1_1Channel_1_1Sync__op__state.html">Sync_op_state</a></td></tr>
<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">State in <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab40d8133d53135bcc41a12cc27fc8e13" title="The current state of the blocking sync-op mechanism; a variant that broadly describes the state as: n...">m_sync_op_state</a>, when a sync-op is in fact in progress, meaning <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab40d8133d53135bcc41a12cc27fc8e13" title="The current state of the blocking sync-op mechanism; a variant that broadly describes the state as: n...">m_sync_op_state</a> is not null.  <a href="structipc_1_1transport_1_1struc_1_1Channel_1_1Sync__op__state.html#details">More...</a><br /></td></tr>
<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pub-types" name="pub-types"></a>
Public Types</h2></td></tr>
<tr class="memitem:a9426e8e562dd4c9ea1bc1f69f47bb99f"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f">Sync_io_obj</a> = <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html">sync_io::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;</td></tr>
<tr class="memdesc:a9426e8e562dd4c9ea1bc1f69f47bb99f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Useful for generic programming, the <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code>-pattern counterpart to <code>*this</code> type.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f">More...</a><br /></td></tr>
<tr class="separator:a9426e8e562dd4c9ea1bc1f69f47bb99f"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ae01d976c856e82b4370e9e69e6128cff"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae01d976c856e82b4370e9e69e6128cff">Async_io_obj</a> = <a class="el" href="classipc_1_1transport_1_1Null__peer.html">Null_peer</a></td></tr>
<tr class="memdesc:ae01d976c856e82b4370e9e69e6128cff"><td class="mdescLeft">&#160;</td><td class="mdescRight">You may disregard.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#ae01d976c856e82b4370e9e69e6128cff">More...</a><br /></td></tr>
<tr class="separator:ae01d976c856e82b4370e9e69e6128cff"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a4a0188052c15cab70d712f41b0e74ba7"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7">Owned_channel</a> = typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a4abac89dbd4d26c79b7915990f751a76">Sync_io_obj::Owned_channel</a></td></tr>
<tr class="memdesc:a4a0188052c15cab70d712f41b0e74ba7"><td class="mdescLeft">&#160;</td><td class="mdescRight">Short-hand for the <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> type passed into ctor and returned by <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a1d0225edcfe5f000f26787d5fa5f6821" title="Access to immutable transport::Channel moved-into *this at construction.">owned_channel()</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7">More...</a><br /></td></tr>
<tr class="separator:a4a0188052c15cab70d712f41b0e74ba7"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a346752b515926a2938ed2adb9de92b1e"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a346752b515926a2938ed2adb9de92b1e">Builder_config</a> = typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a8a59bbc3c6a7191b316b23661d8ba6e3">Sync_io_obj::Builder_config</a></td></tr>
<tr class="memdesc:a346752b515926a2938ed2adb9de92b1e"><td class="mdescLeft">&#160;</td><td class="mdescRight">Short-hand for the builder engine type.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a346752b515926a2938ed2adb9de92b1e">More...</a><br /></td></tr>
<tr class="separator:a346752b515926a2938ed2adb9de92b1e"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ad3ff78f00b7f230562d713ec6cf8499c"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ad3ff78f00b7f230562d713ec6cf8499c">Reader_config</a> = typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a14a7166b2f8c117ce6ddafe943d036fa">Sync_io_obj::Reader_config</a></td></tr>
<tr class="memdesc:ad3ff78f00b7f230562d713ec6cf8499c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Short-hand for the reader engine type.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#ad3ff78f00b7f230562d713ec6cf8499c">More...</a><br /></td></tr>
<tr class="separator:ad3ff78f00b7f230562d713ec6cf8499c"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a27a273ed7e1aca34b721fea22c869a41"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a27a273ed7e1aca34b721fea22c869a41">Msg_body</a> = typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a34e183c252390f369f121074772c14c4">Sync_io_obj::Msg_body</a></td></tr>
<tr class="memdesc:a27a273ed7e1aca34b721fea22c869a41"><td class="mdescLeft">&#160;</td><td class="mdescRight">Short-hand for the <code>Message_body</code> template param, this is the capnp message schema transmissible over <code>*this</code>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a27a273ed7e1aca34b721fea22c869a41">More...</a><br /></td></tr>
<tr class="separator:a27a273ed7e1aca34b721fea22c869a41"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a9a0382aa663c177f2a38b576d06b251e"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e">Msg_which</a> = typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a1572a1b1cb4a72ea57f7841a5e78759b">Sync_io_obj::Msg_which</a></td></tr>
<tr class="memdesc:a9a0382aa663c177f2a38b576d06b251e"><td class="mdescLeft">&#160;</td><td class="mdescRight">Short-hand for the <code>Message_body</code> top-level anon capnp-<code>union</code> enumeration.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e">More...</a><br /></td></tr>
<tr class="separator:a9a0382aa663c177f2a38b576d06b251e"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ac2a3a80151886bec41f3fc3a8880e384"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384">Msg_which_in</a> = typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#aa40c3ec3f45cdfea9360f7f35b9ade3c">Sync_io_obj::Msg_which_in</a></td></tr>
<tr class="memdesc:ac2a3a80151886bec41f3fc3a8880e384"><td class="mdescLeft">&#160;</td><td class="mdescRight">Stylistic nicety, indicating that a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a> applies to an in-message rather than an out-message.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384">More...</a><br /></td></tr>
<tr class="separator:ac2a3a80151886bec41f3fc3a8880e384"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a4cc597a9ff8f460f5a773005f0a05805"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4cc597a9ff8f460f5a773005f0a05805">Msg_which_out</a> = typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a7a731cdae5217ed9e867fb80c1fb0fd9">Sync_io_obj::Msg_which_out</a></td></tr>
<tr class="memdesc:a4cc597a9ff8f460f5a773005f0a05805"><td class="mdescLeft">&#160;</td><td class="mdescRight">Stylistic nicety, indicating that a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a> applies to an out-message rather than an in-message.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a4cc597a9ff8f460f5a773005f0a05805">More...</a><br /></td></tr>
<tr class="separator:a4cc597a9ff8f460f5a773005f0a05805"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a860cc99a701576879ebb5a1db58153cc"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc">Msg_out</a> = typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a83fb4462a8d4045bdb56b694bf80393c">Sync_io_obj::Msg_out</a></td></tr>
<tr class="memdesc:a860cc99a701576879ebb5a1db58153cc"><td class="mdescLeft">&#160;</td><td class="mdescRight">Encapsulation of any out-message <em>payload</em> sent or meant to be sent via <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> (et al) by a <code>*this</code> of this type.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc">More...</a><br /></td></tr>
<tr class="separator:a860cc99a701576879ebb5a1db58153cc"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a05d1cd2fc6a81a39c50a24322fb5c165"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165">Msg_in</a> = typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#ac3da0ac1306b63c9e38c47b8c31e3cd2">Sync_io_obj::Msg_in</a></td></tr>
<tr class="memdesc:a05d1cd2fc6a81a39c50a24322fb5c165"><td class="mdescLeft">&#160;</td><td class="mdescRight">Encapsulation of any in-message <em>instance</em> received by a <code>*this</code> of this type.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165">More...</a><br /></td></tr>
<tr class="separator:a05d1cd2fc6a81a39c50a24322fb5c165"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ae1f4b316eaeb7ed520a84d9e21e21063"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae1f4b316eaeb7ed520a84d9e21e21063">Msg_in_ptr</a> = typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#acde2b3866547a30958035203d9d89928">Sync_io_obj::Msg_in_ptr</a></td></tr>
<tr class="memdesc:ae1f4b316eaeb7ed520a84d9e21e21063"><td class="mdescLeft">&#160;</td><td class="mdescRight">A ref-counted handle to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165" title="Encapsulation of any in-message instance received by a *this of this type.">Msg_in</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#ae1f4b316eaeb7ed520a84d9e21e21063">More...</a><br /></td></tr>
<tr class="separator:ae1f4b316eaeb7ed520a84d9e21e21063"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a4d4995b27b7a6944fbcceee7657f6413"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4d4995b27b7a6944fbcceee7657f6413">msg_id_out_t</a> = typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a9b5d17887c9ad1e37081bf4ae4a70e65">Sync_io_obj::msg_id_out_t</a></td></tr>
<tr class="memdesc:a4d4995b27b7a6944fbcceee7657f6413"><td class="mdescLeft">&#160;</td><td class="mdescRight">Short-hand for convenience for the same thing in non-parameterized base <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel__base.html" title="Channel base that contains non-parameterized public items such as tag types and constants.">Channel_base</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a4d4995b27b7a6944fbcceee7657f6413">More...</a><br /></td></tr>
<tr class="separator:a4d4995b27b7a6944fbcceee7657f6413"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pub-methods" name="pub-methods"></a>
Public Member Functions</h2></td></tr>
<tr class="memitem:abe73bfa20ca0207ac8aa63d26d54de83"><td class="memTemplParams" colspan="2">template&lt;typename... Ctor_args&gt; </td></tr>
<tr class="memitem:abe73bfa20ca0207ac8aa63d26d54de83"><td class="memTemplItemLeft" align="right" valign="top">&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#abe73bfa20ca0207ac8aa63d26d54de83">Channel</a> (flow::log::Logger *logger_ptr, Channel_obj &amp;&amp;channel, Ctor_args &amp;&amp;... ctor_args)</td></tr>
<tr class="memdesc:abe73bfa20ca0207ac8aa63d26d54de83"><td class="mdescLeft">&#160;</td><td class="mdescRight">All explicit constructors: signatures match exactly those of <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html" title="sync_io-pattern counterpart to async-I/O-pattern transport::struc::Channel.">struc::sync_io::Channel</a> (a/k/a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f" title="Useful for generic programming, the sync_io-pattern counterpart to *this type.">Sync_io_obj</a>).  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#abe73bfa20ca0207ac8aa63d26d54de83">More...</a><br /></td></tr>
<tr class="separator:abe73bfa20ca0207ac8aa63d26d54de83"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:abf9f4ae00258efb7a5d868a087658ffe"><td class="memItemLeft" align="right" valign="top">&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#abf9f4ae00258efb7a5d868a087658ffe">~Channel</a> ()</td></tr>
<tr class="memdesc:abf9f4ae00258efb7a5d868a087658ffe"><td class="mdescLeft">&#160;</td><td class="mdescRight">Invokes the destructor on the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#abf9f4ae00258efb7a5d868a087658ffe">More...</a><br /></td></tr>
<tr class="separator:abf9f4ae00258efb7a5d868a087658ffe"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a33b4785c212ad88d8322fcc2f4369351"><td class="memTemplParams" colspan="2">template&lt;typename Task_err &gt; </td></tr>
<tr class="memitem:a33b4785c212ad88d8322fcc2f4369351"><td class="memTemplItemLeft" align="right" valign="top">bool&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a33b4785c212ad88d8322fcc2f4369351">start</a> (Task_err &amp;&amp;on_err_func)</td></tr>
<tr class="memdesc:a33b4785c212ad88d8322fcc2f4369351"><td class="mdescLeft">&#160;</td><td class="mdescRight">Permanently memorizes the incoming-direction on-error handler, thus authorizing the emission of any in-messages to handlers registered via <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> (as well as related handlers <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab7cd0bed6392cb155f9ee21071c5226b" title="Registers the handler to invoke when a response in-message arrives, but no response-expectation has b...">set_unexpected_response_handler()</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9ec7ff431b51fec8aacacccb23a2d4e3" title="Registers the handler to invoke when the remote peer encounters the condition that would fire the rem...">set_remote_unexpected_response_handler()</a>).  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a33b4785c212ad88d8322fcc2f4369351">More...</a><br /></td></tr>
<tr class="separator:a33b4785c212ad88d8322fcc2f4369351"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a969bc2021565c542c902fc14ff711c38"><td class="memItemLeft" align="right" valign="top">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a346752b515926a2938ed2adb9de92b1e">Builder_config</a> &amp;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a969bc2021565c542c902fc14ff711c38">struct_builder_config</a> () const</td></tr>
<tr class="memdesc:a969bc2021565c542c902fc14ff711c38"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns the (light-weight) <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a346752b515926a2938ed2adb9de92b1e" title="Short-hand for the builder engine type.">Builder_config</a> specified (directly or indirectly) at construction time.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a969bc2021565c542c902fc14ff711c38">More...</a><br /></td></tr>
<tr class="separator:a969bc2021565c542c902fc14ff711c38"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ade98da21ce433f8ba338e3139760e94a"><td class="memItemLeft" align="right" valign="top">const Builder_config::Builder::Session &amp;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ade98da21ce433f8ba338e3139760e94a">struct_lender_session</a> () const</td></tr>
<tr class="memdesc:ade98da21ce433f8ba338e3139760e94a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns reference to immutable <code>Builder_config::Builder::Session</code> (a light-weight value, as of this writing at most a pointer) specified (directly or indirectly) at construction time.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#ade98da21ce433f8ba338e3139760e94a">More...</a><br /></td></tr>
<tr class="separator:ade98da21ce433f8ba338e3139760e94a"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ade9a8f99615d2c53de1a68989376750d"><td class="memItemLeft" align="right" valign="top">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ad3ff78f00b7f230562d713ec6cf8499c">Reader_config</a> &amp;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ade9a8f99615d2c53de1a68989376750d">struct_reader_config</a> () const</td></tr>
<tr class="memdesc:ade9a8f99615d2c53de1a68989376750d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Deserializing counterpart to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a969bc2021565c542c902fc14ff711c38" title="Returns the (light-weight) Builder_config specified (directly or indirectly) at construction time.">struct_builder_config()</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#ade9a8f99615d2c53de1a68989376750d">More...</a><br /></td></tr>
<tr class="separator:ade9a8f99615d2c53de1a68989376750d"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a1d0225edcfe5f000f26787d5fa5f6821"><td class="memItemLeft" align="right" valign="top">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7">Owned_channel</a> &amp;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a1d0225edcfe5f000f26787d5fa5f6821">owned_channel</a> () const</td></tr>
<tr class="memdesc:a1d0225edcfe5f000f26787d5fa5f6821"><td class="mdescLeft">&#160;</td><td class="mdescRight">Access to immutable <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> moved-into <code>*this</code> at construction.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a1d0225edcfe5f000f26787d5fa5f6821">More...</a><br /></td></tr>
<tr class="separator:a1d0225edcfe5f000f26787d5fa5f6821"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:af9130e43dc985fca4a41f19581048b51"><td class="memItemLeft" align="right" valign="top"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7">Owned_channel</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#af9130e43dc985fca4a41f19581048b51">owned_channel_mutable</a> ()</td></tr>
<tr class="memdesc:af9130e43dc985fca4a41f19581048b51"><td class="mdescLeft">&#160;</td><td class="mdescRight">Access to mutable <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> moved-into <code>*this</code> at construction.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#af9130e43dc985fca4a41f19581048b51">More...</a><br /></td></tr>
<tr class="separator:af9130e43dc985fca4a41f19581048b51"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a9a540a274df3bc7da8fc35ed2a2c1e57"><td class="memItemLeft" align="right" valign="top">const <a class="el" href="namespaceipc_1_1transport_1_1struc.html#a6751c05fb6582a34c7c47ac470c4a48b">Session_token</a> &amp;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a540a274df3bc7da8fc35ed2a2c1e57">session_token</a> () const</td></tr>
<tr class="memdesc:a9a540a274df3bc7da8fc35ed2a2c1e57"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns the (non-nil) logged-in session token; or nil if not in logged-in phase, or if a prior error has hosed the owned <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a540a274df3bc7da8fc35ed2a2c1e57">More...</a><br /></td></tr>
<tr class="separator:a9a540a274df3bc7da8fc35ed2a2c1e57"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a394e0f9cfa5f9bd4ba9ee17d3d54a8b3"><td class="memItemLeft" align="right" valign="top"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc">Msg_out</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a394e0f9cfa5f9bd4ba9ee17d3d54a8b3">create_msg</a> (<a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8">Native_handle</a> &amp;&amp;hndl_or_null=<a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8">Native_handle</a>()) const</td></tr>
<tr class="memdesc:a394e0f9cfa5f9bd4ba9ee17d3d54a8b3"><td class="mdescLeft">&#160;</td><td class="mdescRight">Creates/returns empty out-message, optionally also holding a native handle, to mutate and later <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> (et al).  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a394e0f9cfa5f9bd4ba9ee17d3d54a8b3">More...</a><br /></td></tr>
<tr class="separator:a394e0f9cfa5f9bd4ba9ee17d3d54a8b3"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a160a8d49624f15a2596ee7b0244584b0"><td class="memTemplParams" colspan="2">template&lt;typename On_msg_handler &gt; </td></tr>
<tr class="memitem:a160a8d49624f15a2596ee7b0244584b0"><td class="memTemplItemLeft" align="right" valign="top">bool&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0">expect_msg</a> (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384">Msg_which_in</a> which, On_msg_handler &amp;&amp;on_msg_func)</td></tr>
<tr class="memdesc:a160a8d49624f15a2596ee7b0244584b0"><td class="mdescLeft">&#160;</td><td class="mdescRight">Registers the expectation of up to 1 <em>notification</em> in-message whose <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a> equals <code>which</code>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0">More...</a><br /></td></tr>
<tr class="separator:a160a8d49624f15a2596ee7b0244584b0"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a3376b821b129ca3847484a178e080c67"><td class="memTemplParams" colspan="2">template&lt;typename On_msg_handler &gt; </td></tr>
<tr class="memitem:a3376b821b129ca3847484a178e080c67"><td class="memTemplItemLeft" align="right" valign="top">bool&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67">expect_msgs</a> (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384">Msg_which_in</a> which, On_msg_handler &amp;&amp;on_msg_func)</td></tr>
<tr class="memdesc:a3376b821b129ca3847484a178e080c67"><td class="mdescLeft">&#160;</td><td class="mdescRight">Registers the expectation of 0+ <em>notification</em> in-messages whose <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a> equals <code>which</code>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67">More...</a><br /></td></tr>
<tr class="separator:a3376b821b129ca3847484a178e080c67"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a896bb326a58f433bade75b62f1893462"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a896bb326a58f433bade75b62f1893462">undo_expect_msgs</a> (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384">Msg_which_in</a> which)</td></tr>
<tr class="memdesc:a896bb326a58f433bade75b62f1893462"><td class="mdescLeft">&#160;</td><td class="mdescRight">Unregisters the expectation earlier-registered with <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a896bb326a58f433bade75b62f1893462">More...</a><br /></td></tr>
<tr class="separator:a896bb326a58f433bade75b62f1893462"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ae645cb58ad9ea6374970f1f32c5da448"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448">send</a> (const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc">Msg_out</a> &amp;msg, const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165">Msg_in</a> *originating_msg_or_null=0, <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a> *err_code=0)</td></tr>
<tr class="memdesc:ae645cb58ad9ea6374970f1f32c5da448"><td class="mdescLeft">&#160;</td><td class="mdescRight">In the synchronous/non-blocking manner of <a class="el" href="classipc_1_1transport_1_1Blob__sender.html#a776b55ae93e65592b90c3943ca99e948" title="In PEER state: Synchronously, non-blockingly sends one discrete message, reliably and in-order,...">Blob_sender::send_blob()</a> or <a class="el" href="classipc_1_1transport_1_1Native__handle__sender.html#ac96b0aa01c286d525f9dcfa6dacc4220" title="In PEER state: Synchronously, non-blockingly sends one discrete message, reliably/in-order,...">Native_handle_sender::send_native_handle()</a> sends the given message to the opposing peer, as a <em>notification</em> (without expecting response).  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448">More...</a><br /></td></tr>
<tr class="separator:ae645cb58ad9ea6374970f1f32c5da448"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a97506bcb695f22e7ca6b480bae5b2346"><td class="memTemplParams" colspan="2">template&lt;typename On_msg_handler &gt; </td></tr>
<tr class="memitem:a97506bcb695f22e7ca6b480bae5b2346"><td class="memTemplItemLeft" align="right" valign="top">bool&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346">async_request</a> (const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc">Msg_out</a> &amp;msg, const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165">Msg_in</a> *originating_msg_or_null, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4d4995b27b7a6944fbcceee7657f6413">msg_id_out_t</a> *id_unless_one_off, On_msg_handler &amp;&amp;on_rsp_func, <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a> *err_code=0)</td></tr>
<tr class="memdesc:a97506bcb695f22e7ca6b480bae5b2346"><td class="mdescLeft">&#160;</td><td class="mdescRight">Identical to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> sends the out-message not as a <em>notification</em> but as a <em>request</em>, registering the expectation of 1+ response(s) to it, async-invoking the provided response handler once reponse(s) arrive(s).  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346">More...</a><br /></td></tr>
<tr class="separator:a97506bcb695f22e7ca6b480bae5b2346"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:aa41aee3c76035f43833078e625e6ef78"><td class="memItemLeft" align="right" valign="top"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae1f4b316eaeb7ed520a84d9e21e21063">Msg_in_ptr</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78">sync_request</a> (const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc">Msg_out</a> &amp;msg, const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165">Msg_in</a> *originating_msg_or_null=0, <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a> *err_code=0)</td></tr>
<tr class="memdesc:aa41aee3c76035f43833078e625e6ef78"><td class="mdescLeft">&#160;</td><td class="mdescRight">Equivalent to the other <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> overload but with no timeout; meaning it shall exit only once either the expected one-off response arrives, or a pipe-hosing error occurs.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78">More...</a><br /></td></tr>
<tr class="separator:aa41aee3c76035f43833078e625e6ef78"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a18100e5af4f5111f1515ff9eef8b1f92"><td class="memItemLeft" align="right" valign="top"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae1f4b316eaeb7ed520a84d9e21e21063">Msg_in_ptr</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a18100e5af4f5111f1515ff9eef8b1f92">sync_request</a> (const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc">Msg_out</a> &amp;msg, const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165">Msg_in</a> *originating_msg_or_null, <a class="el" href="namespaceipc_1_1util.html#ac66141280c3b7295a86b65209f31cc58">util::Fine_duration</a> timeout, <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a> *err_code)</td></tr>
<tr class="memdesc:a18100e5af4f5111f1515ff9eef8b1f92"><td class="mdescLeft">&#160;</td><td class="mdescRight">A blocking (subject to timeout) operation that first acts as-if <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> was invoked in one-off-request mode; then awaits the one-off response and synchronously returns that reponse (or pipe-hosing error, or timeout error).  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a18100e5af4f5111f1515ff9eef8b1f92">More...</a><br /></td></tr>
<tr class="separator:a18100e5af4f5111f1515ff9eef8b1f92"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a34780bd3507a571cb719ce1d59e5d56f"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a34780bd3507a571cb719ce1d59e5d56f">undo_expect_responses</a> (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4d4995b27b7a6944fbcceee7657f6413">msg_id_out_t</a> originating_msg_id)</td></tr>
<tr class="memdesc:a34780bd3507a571cb719ce1d59e5d56f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Unregisters the expectation earlier-registered with the <code>id_unless_one_off != nullptr</code> form of <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a34780bd3507a571cb719ce1d59e5d56f">More...</a><br /></td></tr>
<tr class="separator:a34780bd3507a571cb719ce1d59e5d56f"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ab7cd0bed6392cb155f9ee21071c5226b"><td class="memTemplParams" colspan="2">template&lt;typename On_unexpected_response_handler &gt; </td></tr>
<tr class="memitem:ab7cd0bed6392cb155f9ee21071c5226b"><td class="memTemplItemLeft" align="right" valign="top">bool&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab7cd0bed6392cb155f9ee21071c5226b">set_unexpected_response_handler</a> (On_unexpected_response_handler &amp;&amp;on_func)</td></tr>
<tr class="memdesc:ab7cd0bed6392cb155f9ee21071c5226b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Registers the handler to invoke when a response in-message arrives, but no response-expectation has been registered (via <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>), or the one-off request had been previously satisfied with another response, or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a34780bd3507a571cb719ce1d59e5d56f" title="Unregisters the expectation earlier-registered with the id_unless_one_off != nullptr form of async_re...">undo_expect_responses()</a> has been issued for an open-ended request, or the response is to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> that has timed out.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#ab7cd0bed6392cb155f9ee21071c5226b">More...</a><br /></td></tr>
<tr class="separator:ab7cd0bed6392cb155f9ee21071c5226b"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ad3070c369762b2f5e85555155f65bdaa"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ad3070c369762b2f5e85555155f65bdaa">unset_unexpected_response_handler</a> ()</td></tr>
<tr class="memdesc:ad3070c369762b2f5e85555155f65bdaa"><td class="mdescLeft">&#160;</td><td class="mdescRight">Undoes <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab7cd0bed6392cb155f9ee21071c5226b" title="Registers the handler to invoke when a response in-message arrives, but no response-expectation has b...">set_unexpected_response_handler()</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#ad3070c369762b2f5e85555155f65bdaa">More...</a><br /></td></tr>
<tr class="separator:ad3070c369762b2f5e85555155f65bdaa"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a9ec7ff431b51fec8aacacccb23a2d4e3"><td class="memTemplParams" colspan="2">template&lt;typename On_remote_unexpected_response_handler &gt; </td></tr>
<tr class="memitem:a9ec7ff431b51fec8aacacccb23a2d4e3"><td class="memTemplItemLeft" align="right" valign="top">bool&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9ec7ff431b51fec8aacacccb23a2d4e3">set_remote_unexpected_response_handler</a> (On_remote_unexpected_response_handler &amp;&amp;on_func)</td></tr>
<tr class="memdesc:a9ec7ff431b51fec8aacacccb23a2d4e3"><td class="mdescLeft">&#160;</td><td class="mdescRight">Registers the handler to invoke when the <em>remote</em> peer encounters the condition that would fire the <em>remote</em> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab7cd0bed6392cb155f9ee21071c5226b" title="Registers the handler to invoke when a response in-message arrives, but no response-expectation has b...">set_unexpected_response_handler()</a> handler (regardless of whether one is indeed remotely registered), causing that peer to inform <code>*this</code> of that event in the background.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a9ec7ff431b51fec8aacacccb23a2d4e3">More...</a><br /></td></tr>
<tr class="separator:a9ec7ff431b51fec8aacacccb23a2d4e3"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a1d5415ad72e5758f15fd49d2faabb3e0"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a1d5415ad72e5758f15fd49d2faabb3e0">unset_remote_unexpected_response_handler</a> ()</td></tr>
<tr class="memdesc:a1d5415ad72e5758f15fd49d2faabb3e0"><td class="mdescLeft">&#160;</td><td class="mdescRight">Undoes <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9ec7ff431b51fec8aacacccb23a2d4e3" title="Registers the handler to invoke when the remote peer encounters the condition that would fire the rem...">set_remote_unexpected_response_handler()</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a1d5415ad72e5758f15fd49d2faabb3e0">More...</a><br /></td></tr>
<tr class="separator:a1d5415ad72e5758f15fd49d2faabb3e0"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ab08057edd9832d94ea0e18a17c42200a"><td class="memTemplParams" colspan="2">template&lt;typename Task_err &gt; </td></tr>
<tr class="memitem:ab08057edd9832d94ea0e18a17c42200a"><td class="memTemplItemLeft" align="right" valign="top">bool&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a">async_end_sending</a> (Task_err &amp;&amp;on_done_func)</td></tr>
<tr class="memdesc:ab08057edd9832d94ea0e18a17c42200a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Operating at the unstructured layer, executes a graceful-close send by forwarding to the async <a class="el" href="classipc_1_1transport_1_1Channel.html#a37fcdfdbefd8ee7e374b0596782ad128" title="Performs hndl_snd()-&gt; and/or blob_snd()-&gt; same method, synthesizing completion handlers into one if a...">transport::Channel::async_end_sending()</a> on the owned <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a">More...</a><br /></td></tr>
<tr class="separator:ab08057edd9832d94ea0e18a17c42200a"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a0054bbf18bc769b2a5b95f249e672c0a"><td class="memTemplParams" colspan="2">template&lt;typename On_msg_handler &gt; </td></tr>
<tr class="memitem:a0054bbf18bc769b2a5b95f249e672c0a"><td class="memTemplItemLeft" align="right" valign="top">bool&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a0054bbf18bc769b2a5b95f249e672c0a">expect_log_in_request</a> (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384">Msg_which_in</a> which, On_msg_handler &amp;&amp;on_log_in_req_func)</td></tr>
<tr class="memdesc:a0054bbf18bc769b2a5b95f249e672c0a"><td class="mdescLeft">&#160;</td><td class="mdescRight">In log-in phase as server only: Registers the expectation of up to 1 <em>log-in request</em> in-message whose <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a> equals <code>which</code>, firing the provided handler asynchronously once the <em>log-in response</em> does arrive.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a0054bbf18bc769b2a5b95f249e672c0a">More...</a><br /></td></tr>
<tr class="separator:a0054bbf18bc769b2a5b95f249e672c0a"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pub-static-methods" name="pub-static-methods"></a>
Static Public Member Functions</h2></td></tr>
<tr class="memitem:a08062e4cc99347e94e9e917b382985ee"><td class="memItemLeft" align="right" valign="top">static <a class="el" href="structipc_1_1transport_1_1struc_1_1Heap__fixed__builder_1_1Config.html">Heap_fixed_builder::Config</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a08062e4cc99347e94e9e917b382985ee">heap_fixed_builder_config</a> (const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7">Owned_channel</a> &amp;channel)</td></tr>
<tr class="memdesc:a08062e4cc99347e94e9e917b382985ee"><td class="mdescLeft">&#160;</td><td class="mdescRight">Utility for use when <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a346752b515926a2938ed2adb9de92b1e" title="Short-hand for the builder engine type.">Builder_config</a> template param is <a class="el" href="structipc_1_1transport_1_1struc_1_1Heap__fixed__builder_1_1Config.html" title="Implements Struct_builder::Config sub-concept.">Heap_fixed_builder::Config</a>, this returns such a <code>Config</code> constructed with the most efficient yet safe values.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a08062e4cc99347e94e9e917b382985ee">More...</a><br /></td></tr>
<tr class="separator:a08062e4cc99347e94e9e917b382985ee"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a629c06957e1c5fac96d62473f7e18966"><td class="memItemLeft" align="right" valign="top">static <a class="el" href="structipc_1_1transport_1_1struc_1_1Heap__reader_1_1Config.html">Heap_reader::Config</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a629c06957e1c5fac96d62473f7e18966">heap_reader_config</a> (const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7">Owned_channel</a> &amp;channel)</td></tr>
<tr class="memdesc:a629c06957e1c5fac96d62473f7e18966"><td class="mdescLeft">&#160;</td><td class="mdescRight">Deserializing counterpart to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a08062e4cc99347e94e9e917b382985ee" title="Utility for use when Builder_config template param is Heap_fixed_builder::Config, this returns such a...">heap_fixed_builder_config()</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a629c06957e1c5fac96d62473f7e18966">More...</a><br /></td></tr>
<tr class="separator:a629c06957e1c5fac96d62473f7e18966"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pri-types" name="pri-types"></a>
Private Types</h2></td></tr>
<tr class="memitem:ade399eda73424def3da0dd67596d2cff"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ade399eda73424def3da0dd67596d2cff">Mutex</a> = flow::util::Mutex_non_recursive</td></tr>
<tr class="memdesc:ade399eda73424def3da0dd67596d2cff"><td class="mdescLeft">&#160;</td><td class="mdescRight">Short-hand for <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a01c90903e715ebcf64d8b5ea0d114bc0" title="Mutex protecting the in-message/out-message state in *this.">m_mutex</a> type.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#ade399eda73424def3da0dd67596d2cff">More...</a><br /></td></tr>
<tr class="separator:ade399eda73424def3da0dd67596d2cff"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:af0d9dcd9c3ccf8e064f0cca69b30ea25"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#af0d9dcd9c3ccf8e064f0cca69b30ea25">Lock_guard</a> = flow::util::Lock_guard&lt; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ade399eda73424def3da0dd67596d2cff">Mutex</a> &gt;</td></tr>
<tr class="memdesc:af0d9dcd9c3ccf8e064f0cca69b30ea25"><td class="mdescLeft">&#160;</td><td class="mdescRight">Short-hand for <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ade399eda73424def3da0dd67596d2cff" title="Short-hand for m_mutex type.">Mutex</a> lock.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#af0d9dcd9c3ccf8e064f0cca69b30ea25">More...</a><br /></td></tr>
<tr class="separator:af0d9dcd9c3ccf8e064f0cca69b30ea25"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a1df9dd26651017e61d7701bf3af42260"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a1df9dd26651017e61d7701bf3af42260">On_msg_func</a> = <a class="el" href="namespaceipc.html#aa455c7f045059736578ca275fc1a851f">Function</a>&lt; void(<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae1f4b316eaeb7ed520a84d9e21e21063">Msg_in_ptr</a> &amp;&amp;msg)&gt;</td></tr>
<tr class="memdesc:a1df9dd26651017e61d7701bf3af42260"><td class="mdescLeft">&#160;</td><td class="mdescRight">Concrete type corresponding to <code>On_msg_handler</code> template param: in-message handler.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a1df9dd26651017e61d7701bf3af42260">More...</a><br /></td></tr>
<tr class="separator:a1df9dd26651017e61d7701bf3af42260"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pri-methods" name="pri-methods"></a>
Private Member Functions</h2></td></tr>
<tr class="memitem:a8ca2772b0a657cb55f140a6273e528b9"><td class="memTemplParams" colspan="2">template&lt;bool MSG_ELSE_LOG_IN, typename On_msg_handler &gt; </td></tr>
<tr class="memitem:a8ca2772b0a657cb55f140a6273e528b9"><td class="memTemplItemLeft" align="right" valign="top">bool&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a8ca2772b0a657cb55f140a6273e528b9">expect_msg_impl</a> (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384">Msg_which_in</a> which, On_msg_handler &amp;&amp;on_msg_func)</td></tr>
<tr class="memdesc:a8ca2772b0a657cb55f140a6273e528b9"><td class="mdescLeft">&#160;</td><td class="mdescRight">Implements the one-off expect-message APIs <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a0054bbf18bc769b2a5b95f249e672c0a" title="In log-in phase as server only: Registers the expectation of up to 1 log-in request in-message whose ...">expect_log_in_request()</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a8ca2772b0a657cb55f140a6273e528b9">More...</a><br /></td></tr>
<tr class="separator:a8ca2772b0a657cb55f140a6273e528b9"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pri-attribs" name="pri-attribs"></a>
Private Attributes</h2></td></tr>
<tr class="memitem:a01c90903e715ebcf64d8b5ea0d114bc0"><td class="memItemLeft" align="right" valign="top"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ade399eda73424def3da0dd67596d2cff">Mutex</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a01c90903e715ebcf64d8b5ea0d114bc0">m_mutex</a></td></tr>
<tr class="memdesc:a01c90903e715ebcf64d8b5ea0d114bc0"><td class="mdescLeft">&#160;</td><td class="mdescRight">Mutex protecting the in-message/out-message state in <code>*this</code>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a01c90903e715ebcf64d8b5ea0d114bc0">More...</a><br /></td></tr>
<tr class="separator:a01c90903e715ebcf64d8b5ea0d114bc0"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ab40d8133d53135bcc41a12cc27fc8e13"><td class="memItemLeft" align="right" valign="top">std::optional&lt; <a class="el" href="structipc_1_1transport_1_1struc_1_1Channel_1_1Sync__op__state.html">Sync_op_state</a> &gt;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab40d8133d53135bcc41a12cc27fc8e13">m_sync_op_state</a></td></tr>
<tr class="memdesc:ab40d8133d53135bcc41a12cc27fc8e13"><td class="mdescLeft">&#160;</td><td class="mdescRight">The current state of the blocking sync-op mechanism; a <code>variant</code> that broadly describes the state as: no sync-op in progress, sync-op in progress sans result, sync-op in progress with result that has not yet been returned to user (sync-op almost over).  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#ab40d8133d53135bcc41a12cc27fc8e13">More...</a><br /></td></tr>
<tr class="separator:ab40d8133d53135bcc41a12cc27fc8e13"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:abb0ed2e666191dd85e543072077bf38b"><td class="memItemLeft" align="right" valign="top"><a class="el" href="structipc_1_1transport_1_1struc_1_1Channel_1_1Sync__op__state.html#a6b5142da7049fc212faff3914e69379b">Sync_op_state::id_t</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#abb0ed2e666191dd85e543072077bf38b">m_sync_op_state_id</a></td></tr>
<tr class="memdesc:abb0ed2e666191dd85e543072077bf38b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Next unique ID for <a class="el" href="structipc_1_1transport_1_1struc_1_1Channel_1_1Sync__op__state.html#ad6f8e016b2abc3654e1915cc8c77c268" title="See id_t; used to check an arriving sync op result as belonging to the currently-waiting sync op.">Sync_op_state::m_id</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#abb0ed2e666191dd85e543072077bf38b">More...</a><br /></td></tr>
<tr class="separator:abb0ed2e666191dd85e543072077bf38b"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a5e905a57052ba370d8d2f45a361982d8"><td class="memItemLeft" align="right" valign="top">flow::async::Task_asio_err&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a5e905a57052ba370d8d2f45a361982d8">m_snd_end_sending_on_done_func_or_empty</a></td></tr>
<tr class="memdesc:a5e905a57052ba370d8d2f45a361982d8"><td class="mdescLeft">&#160;</td><td class="mdescRight">Analogous to Async_adapter_sender::m_end_sending_on_done_func_or_empty.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a5e905a57052ba370d8d2f45a361982d8">More...</a><br /></td></tr>
<tr class="separator:a5e905a57052ba370d8d2f45a361982d8"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a2184077da7828589d20d7f92a31a6394"><td class="memItemLeft" align="right" valign="top">flow::async::Single_thread_task_loop&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a2184077da7828589d20d7f92a31a6394">m_worker</a></td></tr>
<tr class="memdesc:a2184077da7828589d20d7f92a31a6394"><td class="mdescLeft">&#160;</td><td class="mdescRight">Thread W used to (1) fire user-provided handlers and (2) perform any async work requested by <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aefee55a9e754a63ce52766d6c65df92c" title="The core struc::Channel engine, implementing the sync_io pattern (see util::sync_io doc header).">m_sync_io</a>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a2184077da7828589d20d7f92a31a6394">More...</a><br /></td></tr>
<tr class="separator:a2184077da7828589d20d7f92a31a6394"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:aefee55a9e754a63ce52766d6c65df92c"><td class="memItemLeft" align="right" valign="top"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f">Sync_io_obj</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aefee55a9e754a63ce52766d6c65df92c">m_sync_io</a></td></tr>
<tr class="memdesc:aefee55a9e754a63ce52766d6c65df92c"><td class="mdescLeft">&#160;</td><td class="mdescRight">The core <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a></code> engine, implementing the <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code> pattern (see <a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">util::sync_io</a> doc header).  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#aefee55a9e754a63ce52766d6c65df92c">More...</a><br /></td></tr>
<tr class="separator:aefee55a9e754a63ce52766d6c65df92c"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="related" name="related"></a>
Related Functions</h2></td></tr>
<tr><td class="ititle" colspan="2"><p >(Note that these are not member functions.) </p>
</td></tr>
<tr class="memitem:a0351bb14f40312b30e6cae4927f3373b"><td class="memTemplParams" colspan="2">template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </td></tr>
<tr class="memitem:a0351bb14f40312b30e6cae4927f3373b"><td class="memTemplItemLeft" align="right" valign="top">std::ostream &amp;&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a0351bb14f40312b30e6cae4927f3373b">operator&lt;&lt;</a> (std::ostream &amp;os, const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt; &amp;val)</td></tr>
<tr class="memdesc:a0351bb14f40312b30e6cae4927f3373b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Prints string representation of the given <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> to the given <code>ostream</code>.  <a href="classipc_1_1transport_1_1struc_1_1Channel.html#a0351bb14f40312b30e6cae4927f3373b">More...</a><br /></td></tr>
<tr class="separator:a0351bb14f40312b30e6cae4927f3373b"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table>
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
<div class="textblock"><div class="compoundTemplParams">template&lt;typename Channel_obj, typename Message_body, typename Struct_builder_config, typename Struct_reader_config&gt;<br />
class ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;</div><p >Owning and wrapping a pre-connected <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> peer (an endpoint of an established channel over which <em>unstructured</em> messages and optionally native handles can be transported), this template is the central pillar of the <a class="el" href="namespaceipc_1_1transport_1_1struc.html" title="Sub-module of Flow-IPC module ipc::transport providing transmission of structured messages specifical...">ipc::transport::struc</a> (<em>structured layer</em>), capable of communicating structured capnp-schema-based messages (and native handles). </p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html" title="sync_io-pattern counterpart to async-I/O-pattern transport::struc::Channel.">sync_io::Channel</a> and <a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">util::sync_io</a> doc headers. The latter describes a general pattern which the former implements. In general we recommend you use a <code>*this</code> rather than a <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html" title="sync_io-pattern counterpart to async-I/O-pattern transport::struc::Channel.">sync_io::Channel</a> &ndash; but you may have particular needs (summarized in <a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">util::sync_io</a> doc header) that would make you decide otherwise.</dd></dl>
<h3>Context (short version)</h3>
<p ><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> (and its <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code> counterpart &ndash; and, internally, its core) along with <a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__out.html" title="A structured out-message suitable to be sent via struc::Channel::send() (et al).">Msg_out</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__in.html" title="A structured in-message instance suitable as received and emittable (to user) by struc::Channel.">Msg_in</a> essentially <em>are</em> the <a class="el" href="namespaceipc_1_1transport.html" title="Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...">ipc::transport</a> structured layer. We also suspect that (and designed <a class="el" href="namespaceipc_1_1transport.html" title="Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...">ipc::transport</a> accordingly) most users of <a class="el" href="namespaceipc_1_1transport.html" title="Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...">ipc::transport</a>, or arguably even Flow-IPC at large, will mostly care about the work they can do with <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> and nothing else. Users just want to send structured messages (and sometimes native handles) in some forward-compatible protocol. Everything else &ndash; sessions, unstructured-layer channels, the queues and/or socket streams comprised by those channels &ndash; are the necessary but ideally-ignored-most-of-the-time <em>means</em> leading to the <em>ultimate end</em> of having a working <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> over which to exchange that structured stuff with the peer's <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> counterpart.</p>
<h3>Context (more in-depth)</h3>
<p >This has certain broad implications. Suppose one first familiarizes themselves with the unstructured layer (concepts <a class="el" href="classipc_1_1transport_1_1Blob__sender.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order sending ...">Blob_sender</a>, <a class="el" href="classipc_1_1transport_1_1Blob__receiver.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order receivin...">Blob_receiver</a>, <a class="el" href="classipc_1_1transport_1_1Native__handle__sender.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order sending ...">Native_handle_sender</a>, <a class="el" href="classipc_1_1transport_1_1Native__handle__receiver.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order receivin...">Native_handle_receiver</a>; bundling class template <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>; concept impls &ndash; classes/class templates <a class="el" href="classipc_1_1transport_1_1Native__socket__stream.html" title="Implements both Native_handle_sender and Native_handle_receiver concepts by using a stream-oriented U...">Native_socket_stream</a>, <a class="el" href="classipc_1_1transport_1_1Blob__stream__mq__sender.html" title="Implements Blob_sender concept by using an adopted Persistent_mq_handle MQ handle to an MQ (message q...">Blob_stream_mq_sender</a>, <a class="el" href="classipc_1_1transport_1_1Blob__stream__mq__receiver.html" title="Implements Blob_receiver concept by using an adopted Persistent_mq_handle MQ handle to an MQ (message...">Blob_stream_mq_receiver</a>; low-level details like the MQ-related API and server class <a class="el" href="classipc_1_1transport_1_1Native__socket__stream__acceptor.html" title="A server object that binds to a Shared_name and listens for incoming Native_socket_stream connect att...">Native_socket_stream_acceptor</a>). If one indeed is familiar with that whole unstructured API, they'll note: <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> API is quite different. Particularly it's very different in terms of how one handles <em>in-messages</em> (receiving). To wit:</p><ul>
<li>The unstructured APIs are roughly boost.asio-like (though in fact <em>not</em> requiring any integration with actual boost.asio). That is:<ul>
<li>Each async operation is invoked via an <code>X.async_F(H)</code> method, to which one passes the handler <code>H</code> to invoke; and <code>H()</code> is called <em>exactly</em> once: when the async op completes (with or without error); or <code>X</code> is destroyed first (in which case an <code>operation_aborted</code>-like error code is emitted to <code>H()</code>).</li>
<li>If more than one <code>X.async_F()</code> is invoked, for a given <code>F</code> (e.g., 3 <a class="el" href="classipc_1_1transport_1_1Blob__receiver.html#a8bc6642dbf4b5e3fdee9f3442f2bbe84" title="In PEER state: Asynchronously awaits one discrete message – as sent by the opposing peer via Blob_sen...">Blob_receiver::async_receive_blob()</a> outstanding calls on one <a class="el" href="classipc_1_1transport_1_1Blob__receiver.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order receivin...">Blob_receiver</a>), then they are queued inside X as needed, with each arriving result firing 1 handler, dequeuing it in FIFO order.</li>
<li>If a pipe-hosing error occurs, it is fed to all queued handlers (i.e., the internal queue is cleared) and any future-invoked-async-API-passed handlers also.</li>
</ul>
</li>
<li>By contrast: The structured (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a>) API is not at all boost.asio-like.<ul>
<li>There are no <code>async_F()</code> async ops as such. There is no FIFO-queueing of handlers. Instead:</li>
<li>One registers events handlers for each type of event in which one is interested. While it's possible to auto-unregister an event handler after it fires once, the general case is that an event handler registration is permanent until explicitly undone.<ul>
<li>As a sub-case of this paradigm, the act of sending an out-message can be optionally paired with registering an event handler for when (and if) the other peer responds to that specific out-message with a response in-message. Thus request/response semantics (while optional) are built-in.</li>
<li>As a sub-case of this paradigm, a single error handler is registered; if a pipe-hosing error occurs, then that handler is invoked just once &ndash; as opposed to invoking all the other stored handlers with that same <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a>.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p >As for the <em>out-message</em> (sending) API: It is actually extremely similar to the unstructured layer's already admirably simple API. To recap:</p><ul>
<li>If you want to send a message, you invoke <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>. Each is non-blocking <em>and</em> synchronous <em>yet</em> it cannot fail due to a would-block condition. There is no asynchronous send op!<ul>
<li>Alternatively use <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> which is a blocking, optionally subject to timeout, version of <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>. It will block until a one-off response is received to the sent message (or timeout, or error) and return that response synchronously (if indeed successful).</li>
<li>Note that, while <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> is blocking, it can be used for very quick request-response exchanges; indeed that is its main use case. For example, a memory-allocation op might contact the memory-allocating process and return once that process has acknowledged completing the alloc request.</li>
</ul>
</li>
<li>Graceful closing is forwarded to the unstructured layer. The <a class="el" href="classipc_1_1transport_1_1Blob__sender.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order sending ...">Blob_sender</a>, <a class="el" href="classipc_1_1transport_1_1Native__handle__sender.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order sending ...">Native_handle_sender</a>, <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> API is mimicked by simply passing-through to the owned <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a>.<ul>
<li>This features an asynchronous component. Discussion omitted here; just see <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a>.</li>
</ul>
</li>
</ul>
<p >However the out-message (sending) API adds an important (optional but highly encouraged) capability:</p><ul>
<li>Every out-message can be allocated in SHM (shared memory) instead of heap; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> (et al) then transparently sends (copies into transport, on other side copies out of transport) a tiny <em>handle</em> to the message.<ul>
<li>This is enabled, or disabled, for the entire <code>*this</code> via compile-time parameters and ctor args. After that the API is completely identical regardless of whether this full <em>zero-copy</em> mode is in use or not.</li>
</ul>
</li>
<li>An out-message can be reused and sent again. It can be modified in-between. It would be practical to use this technique to store complex data structures integral to your application as opposed to a mere messaging focus. This does not <em>require</em> the SHM-backed (zero-copy) mode, but it greatly improves performance when sharing with another process.<ul>
<li>This is an alternative to storing a C++ data structure, such as a <code>vector</code> of <code>map</code>s of ..., in SHM manually and transmitting a handle manually. Discussion of details of this is outside the scope here, but you should be aware that it's the alternative approach for structured-data storage in SHM and its IPC. They each have their pros/cons.</li>
</ul>
</li>
</ul>
<p >Long story short:</p><ul>
<li>Sending is simple as in the unstructured layer.<ul>
<li>However zero-copy backing of the structured message's serialization in SHM allows for far improved perf.</li>
</ul>
</li>
<li>Receiving follows an event-handler-registration model, instead of the unstructured layer's preferred async-op-and-handler model (as inspired by boost.asio).</li>
</ul>
<h3>Overview: How to use it, why to use it</h3>
<p >How to use this thing? Broadly speaking:</p><ol type="1">
<li>One first establishes a channel connection (obtains a <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> in PEER state). See <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>. Attention: You will need a <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code>-pattern-peer-bearing <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> (which is enforced at compile-time); formally <code>Owned_channel::S_IS_SYNC_IO_OBJ == true</code> is required. <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> emits such <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">Channel</a></code>s. If you are manually assembling a <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">Channel</a></code> (or alias or data-less sub-class), then attaining fresh PEER-state peer objects of the <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code>-pattern variety should be equally easy. In the case of <a class="el" href="classipc_1_1transport_1_1Native__socket__stream.html" title="Implements both Native_handle_sender and Native_handle_receiver concepts by using a stream-oriented U...">Native_socket_stream</a> specifically, you can perform <code>.sync_connect()</code> on a <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code>-pattern <a class="el" href="classipc_1_1transport_1_1sync__io_1_1Native__socket__stream.html" title="Implements both sync_io::Native_handle_sender and sync_io::Native_handle_receiver concepts by using a...">transport::sync_io::Native_socket_stream</a>; on success bundle it into <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">Channel</a></code>.</li>
<li>One selects the capnp message schema they wish to use. In other words, what kinds of messages does one want to send? This determines the choice of the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a27a273ed7e1aca34b721fea22c869a41" title="Short-hand for the Message_body template param, this is the capnp message schema transmissible over *...">Msg_body</a> template parameter.</li>
<li>One selects a technique as to where/how out-messages (and consequently in-messages) will be stored in RAM: SHM (for full zero-copy performance) or heap (for zero-copy on either side of the low-level transport).. (Details omitted here, but for the sake of this brief recap let's consider this a formality.)</li>
<li>One then constructs the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a>, passing the <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> (and the config from previous bullet point) into ctor &ndash; which is moved-into the resulting <code>*this</code>.</li>
<li>One then exchanges messages (and, if desired, native handles) with the matching <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> on the other side via the <code>*this</code> transmission API.</li>
<li>When <code>*this</code> is destroyed, so is the owned <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> (and no earlier).</li>
</ol>
<p >So <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> "eats" (via <code>std::move()</code>) a presumably fresh (no traffic exchanged) <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> and all further work on the <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> is through <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a>.</p>
<p >What does <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> add, broadly speaking, that <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> does not already have? Why even bother? Answer:</p><ul>
<li>Firstly, each message no longer consists of an (optional unstructured binary blob, optional <a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8" title="Convenience alias for the commonly used type util::Native_handle.">Native_handle</a>) pair. Instead if consists of a (structured capnp-schema-based message, optional <a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8" title="Convenience alias for the commonly used type util::Native_handle.">Native_handle</a>) pair. In other words this class adds the (mandatory) ability to send <em>structured</em> data instead of mere binary blobs. The schema language of choice is Cap'n Proto (capnp), which allows for zero-copy perf <em>at least</em> until blobs enter the transport and after they exit the transport.<ul>
<li>By choosing to use SHM-based serialization storage for out-messages, zero-copy perf can be extended end-to-end, meaning only a short handle is ever copied into the transport and out of it on the receiving side.</li>
</ul>
</li>
<li>Secondly it establishes some convenient protocol notions on top of the basic message-boundary-respecting/reliable functionality of <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>.<ul>
<li>Message type (a/k/a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a>): While <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a27a273ed7e1aca34b721fea22c869a41" title="Short-hand for the Message_body template param, this is the capnp message schema transmissible over *...">Msg_body</a> can specify an essentially arbitrarily complex schema for what messages can be sent, with <code>*this</code> API being generally agnostic as to its details, it does establish one simple standard: The message schema <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a27a273ed7e1aca34b721fea22c869a41" title="Short-hand for the Message_body template param, this is the capnp message schema transmissible over *...">Msg_body</a> <em>must</em> feature a top-level anonymous (capnp) <em>union</em>, with the "which" enumerator specifying the type of message that it is. E.g., something approximating HTTP might have the top-level union specifying either a GET, POST, or CONNECT message type, with each one then featuring its own arbitrary capnp <code>struct</code> sub-schema, specifying what data come along with that type of message.<ul>
<li><em>Message type demuxing</em>: Based on this, one sets separate handlers for each individual value for an in-message's <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a>.<ul>
<li>One-off demuxing: One can register the expectation for at most 1 message of a particular <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a> type. Then, when it is received, the expectation registration for that <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a> is auto-removed, as the user-supplied handler fires.</li>
<li>Open-ended demuxing: Alternatively one can set a permanent (unless explicitly unregistered later) expectation for a given <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a>. Then the user-supplied handler will fire each time a matching in-message arrives.</li>
<li>(Queuing) Any messages that have no expect-this-<code>Msg_which</code> handler registered are queued inside <code>*this</code>. Registering a demux expectation later will immediately feed matching queued such in-messages, as if they'd arrived right then.</li>
</ul>
</li>
</ul>
</li>
<li><em>Request/response demuxing</em>: Any message one sends can optionally be specified to be expecting response in-message(s). This is the alternative to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a>-based demuxing. This establishes a basic request/response paradigm.<ul>
<li>One-off response demuxing: One can specify that the given out-message expects up to exactly 1 response.</li>
<li>Open-ended response demuxing: One can instead specify that any number of responses may arrive (until one explicitly unregisters this expectation).</li>
<li>(Note) If a response in-message arrives, while <code>*this</code> has no response expectation registered, it is an error. However it is not necessarily a fatal error: There is a mechanism allowing the user to deal with this situation should it arise. However a properly designed protocol would eliminate this possibility in practice (informally speaking).</li>
</ul>
</li>
<li>A single full-duplex pipe: <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>, one notes, can be a bundle of up to 2 full-duplex pipes (though at least 1 is of course required): one for blobs only; one for blob/<code>Native_handle</code> combos. The 2 do not interact; therefore if one were to use both in parallel, various questions arise as to how (and why!) to use this functionality. <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> elides these details completely and deals with them internally. Bottom line:<ul>
<li><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> API models a single full-duplex pipe capable of transmitting messages, each of which is <em>either</em> just a structured message <em>or</em> a structured message plus <a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8" title="Convenience alias for the commonly used type util::Native_handle.">Native_handle</a>. (The latter capability, naturally, is removed, if <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> lacks a handles pipe.) Internally the <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> pipes are leveraged in such a way as to maximize performance.</li>
<li>Messages arrive in the same order as they are sent (as determined by the order of <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> (et al) calls on the sender <code>*this</code>).<ul>
<li>If a message arrives that has no event handler registered, then it is queued inside <code>*this</code>, as explained above. They are queued, and therefore popped if/when a handler is registered, in the same order as they arrived.</li>
<li>Suppose message with sequence # 5 has arrived but had to be queued due to lacking a registered handler. Suppose message with sequence # 6 has arrived and <em>does</em> have a registered handler. Message 6 will then be emitted to the user; in other words the act of being queued does not preclude the emission of subsequent messages.</li>
</ul>
</li>
</ul>
</li>
<li>Thirdly, there are some (mandatory) safety features. These are almost completely hidden from the user in regular operation. To the extent they are not, it has to do with the <em>log-in</em> feature. This is discussed separately below. Typically one need not worry about it.</li>
</ul>
</li>
</ul>
<h3>How to use it (deep-dive) (log-in excluded)</h3>
<p >Naturally there are two directions of transmission, sending out-messages and receiving in-messages. About the former first:</p>
<p >To transmit an out-message:</p><ul>
<li>Call <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a394e0f9cfa5f9bd4ba9ee17d3d54a8b3" title="Creates/returns empty out-message, optionally also holding a native handle, to mutate and later send(...">create_msg()</a>; this yields a cheaply-<code>move()</code>able out-message: <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a>. (See <a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__out.html" title="A structured out-message suitable to be sent via struc::Channel::send() (et al).">Msg_out</a> doc header for formal public API.) You may also construct this directly &ndash; even without a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> in existence at all; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a394e0f9cfa5f9bd4ba9ee17d3d54a8b3" title="Creates/returns empty out-message, optionally also holding a native handle, to mutate and later send(...">create_msg()</a> merely helps by supplying the serialize/deserialize parameters (a/k/a builder/reader config) for you.</li>
<li>Fill out its contents: <code>M-&gt;body_root()</code> is a <code>Msg_body::Builder*</code>, where <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a27a273ed7e1aca34b721fea22c869a41" title="Short-hand for the Message_body template param, this is the capnp message schema transmissible over *...">Msg_body</a> is determined by your choice of schema (<code>Message_body</code> template param); and <code>Msg_body::Builder</code> is the capnp-generated mutating API. For example: <code>M-&gt;body_root()-&gt;initCoolRequest().setCoolField(57);</code><ul>
<li>sets the message type to <code>Msg_body::Which::COOL_REQUEST</code> and initializes a blank <code>CoolRequest</code> capnp-struct;</li>
<li>mutates the field <code>coolField</code> &ndash; presumably an integer of some kind in this example &ndash; to equal 57.</li>
</ul>
</li>
<li>Send it: <code>send(M)</code> or <code>async_request(M)</code>. Each is non-blocking, synchronous, and cannot would-block.<ul>
<li>If <code>M</code> is a response to some in-message <code>I</code>, use <code>send/async_request(M, I, ...)</code>. Otherwise use <code>send/async_request(M, nullptr, ...)</code>.</li>
<li>If you expect <em>response</em> message(s) to <code>M</code>, use <code>async_request(M, ..., &amp;id, H)</code>, where:<ul>
<li>Set <code>&amp;id</code> to <code>nullptr</code> if one expects at most 1 response to <code>M</code>; otherwise non-null.<ul>
<li>In the latter case optionally use <code>undo_expect_responses(id)</code> to indicate no further responses to the out-message instance sent by that <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> call are expected.</li>
</ul>
</li>
<li><code>H</code> is the handler for the reponse(s); <code>H(I)</code> shall be invoked, where <code>I</code> is the response in-message.</li>
</ul>
</li>
</ul>
</li>
<li>Alternatively to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>: <code>sync_request(M)</code>. This is similar, but instead of returning it awaits the response and returns that response once received. Note that by definition such a request is one-off (exactly 1 response is expected). <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> can optionally specify a timeout.</li>
<li>Note: See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> doc header. TL;DR: You should call this when done using <code>*this</code>; then destroy <code>*this</code> once the async-handler you passed to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> has fired.</li>
</ul>
<p >As usual, the incoming direction is somewhat more complex. It is also different from lower-level APIs such as boost.asio sockets and our various <code><a class="el" href="classipc_1_1transport_1_1Blob__sender.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order sending ...">Blob_sender</a></code>s and the like.</p>
<p >Internally, all in-messages that do arrive on the "wire" are received immediately; each in-message at that point is then handled in exactly one of the following ways. (Here we do not discuss pipe-hosing errors, yet.) A given in-message <code>I</code> is handled thus:</p><ul>
<li>If <code>I</code> is not a response to an earlier out-message <code>M</code>:<ul>
<li>If <code>I</code> is being expected via an earlier <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a> or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a> call: <em>Emit</em> <code>I</code> to that user handler.</li>
<li>Else: queue it inside <code>*this</code> silently.</li>
</ul>
</li>
<li>Else:<ul>
<li>If <code>I</code> is being expected via a response-expectation, as registered in <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> (see above): <em>Emit</em> <code>I</code> to that user handler, or return it via <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> synchronously (whichever applies).</li>
<li>Else: it is a non-pipe hosing error condition. While you should (informally speaking) avoid this, if it does occur, you can handle it as you see fit. See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab7cd0bed6392cb155f9ee21071c5226b" title="Registers the handler to invoke when a response in-message arrives, but no response-expectation has b...">set_unexpected_response_handler()</a>. See also <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9ec7ff431b51fec8aacacccb23a2d4e3" title="Registers the handler to invoke when the remote peer encounters the condition that would fire the rem...">set_remote_unexpected_response_handler()</a>. Spoiler alert: This condition is emitted on both sides: locally, indicating an unexpected response arrived; and remotely, indicating that side <em>issued</em> an unexpected response.</li>
</ul>
</li>
</ul>
<p >Hence there are exactly 3 ways to register a handler for in-messages.</p><ul>
<li>Call <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a> or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a> to expect a particular type of <em>unsolicited</em> (non-response) message. <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a> indicates up to 1 such message shall be expected; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a> indicates 0+ such messages, until <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a896bb326a58f433bade75b62f1893462" title="Unregisters the expectation earlier-registered with expect_msgs().">undo_expect_msgs()</a>.<ul>
<li>If <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a> or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a> is invoked, and matching message(s) are queued inside <code>*this</code> (per above) at that time, <code>*this</code> behaves as-if those messages had just arrived. I.e., they are immediately <em>emitted</em>.</li>
</ul>
</li>
<li>Call <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> to expect a response to a particular out-message.</li>
<li>Call <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> to send request and synchronously await one-off response to that particular out-message.</li>
</ul>
<p >Example:</p><ul>
<li>I am a server, and I expect GET and POST messages. I invoke <code>expect_msgs(Msg_which_in::GET_REQ, handle_get_req)</code> and <code>expect_msgs(Msg_which::POST_REQ, handle_post_req)</code>. <code>handle_get_req(x)</code> shall be invoked for each incoming GET_REQ <code>x</code> and similarly for the POSTs.</li>
<li>I am a client, and I issue GET and POST messages. I invoke <code>async_request(x, ..., nullptr, handle_get_rsp)</code> for a GET and <code>async_request(y, ..., nullptr, handle_post_rsp)</code>, where earlier one did:<ul>
<li><code>x = ....<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a394e0f9cfa5f9bd4ba9ee17d3d54a8b3" title="Creates/returns empty out-message, optionally also holding a native handle, to mutate and later send(...">create_msg()</a></code>; <code>x-&gt;body_root()-&gt;initGetReq().set{Url|HostHeader}(...)</code>;</li>
<li><code>y = ....<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a394e0f9cfa5f9bd4ba9ee17d3d54a8b3" title="Creates/returns empty out-message, optionally also holding a native handle, to mutate and later send(...">create_msg()</a></code>; <code>y-&gt;body_root()-&gt;initPostReq().set{Url|HostHeader|PostBody}(...)</code>.</li>
</ul>
</li>
</ul>
<p >Last but not least: How does one read the contents of an incoming message? For both paths &ndash; unsolicited message expectation via <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>/expect_msgs() + response message expectation via <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> alike &ndash; the user-provided handler shall be of the form: <code>H(I&amp;&amp;)</code>, where <code>I</code> is a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae1f4b316eaeb7ed520a84d9e21e21063" title="A ref-counted handle to Msg_in.">Msg_in_ptr</a>, a ref-counted handle to a new in-message. (See <a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__in.html" title="A structured in-message instance suitable as received and emittable (to user) by struc::Channel.">Msg_in</a> doc header for the formal public API.) Note the <code>&amp;&amp;</code>: it is an rvalue reference to the <code>shared_ptr</code>, rather than a <code>const &amp;</code>, in case you'd like to <code>move()</code> it somewhere for perf instead of ref-counting increment/decrement.</p><ul>
<li><code>I-&gt;body_root()</code> is a <code>const Msg_body::Reader&amp;</code>, where <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a27a273ed7e1aca34b721fea22c869a41" title="Short-hand for the Message_body template param, this is the capnp message schema transmissible over *...">Msg_body</a> is as explained earlier, and <code>Msg_body::Reader</code> is the capnp-generated accessor API. For example: <code>I-&gt;body_root().getCoolRequest().getCoolField()</code> shall equal 57 on the other end, following the earlier out-message example.</li>
<li>In the case of unsolicited messages: <code>I-&gt;body_root().which()</code> shall equal the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384" title="Stylistic nicety, indicating that a Msg_which applies to an in-message rather than an out-message.">Msg_which_in</a> passed to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a> or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a>. Therefore one can perform <code>I-&gt;body_root().getCoolRequest()</code> without fear it's not actually a <code>COOL_REQUEST</code> (which would yield a capnp exception).</li>
<li>In the case of response messages: <code>I-&gt;body_root().which()</code> can be anything (i.e., <code>*this</code> will not enforce anything about it). It is up to you to design that protocol.<ul>
<li>I (ygoldfel) considered enforcing a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384" title="Stylistic nicety, indicating that a Msg_which applies to an in-message rather than an out-message.">Msg_which_in</a> expectation for responses, to be supplied with <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>. However it seemed too restrictive to mandate it. <dl class="todo"><dt><b><a class="el" href="todo.html#_todo000023">Todo:</a></b></dt><dd>Consider adding the <em>optional</em> expectation of a particular <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384" title="Stylistic nicety, indicating that a Msg_which applies to an in-message rather than an out-message.">Msg_which_in</a> when registering expected responses in <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">struc::Channel::async_request()</a>.</dd></dl>
</li>
</ul>
</li>
</ul>
<h3>Thread safety; handler invocation semantics</h3>
<p >In-message handlers, and all other handlers (including those from <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a33b4785c212ad88d8322fcc2f4369351" title="Permanently memorizes the incoming-direction on-error handler, thus authorizing the emission of any i...">start()</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab7cd0bed6392cb155f9ee21071c5226b" title="Registers the handler to invoke when a response in-message arrives, but no response-expectation has b...">set_unexpected_response_handler()</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9ec7ff431b51fec8aacacccb23a2d4e3" title="Registers the handler to invoke when the remote peer encounters the condition that would fire the rem...">set_remote_unexpected_response_handler()</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a>), are invoked from an unspecified thread guaranteed not to be among the user invoking threads. No 2 such handlers shall be invoked concurrently to each other.</p>
<p >Messages are emitted in the order received, except reordered as required by the queueing of not-yet-expected unsolicited messages (as explained earlier).</p>
<p >It is not safe to invoke a non-<code>const</code> API concurrently with another API on the same <code>*this</code>.</p>
<p >You <em>may</em> call <code>*this</code> APIs directly from any in-message handler or other handler. Exception: You may <em>not</em> invoke <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> (or any other <code>sync_*()</code> that may be added over time) from an in-message handler or other handler. Doing so can disrupt the timeliness of delivering other async results.</p>
<p >Informal recommendation: You should off-load most or all handling of in-messages onto your own thread(s) (such as via boost.asio <code>post()</code> or the flow.async infrastructure). For example, suppose your program has some main worker thread U, implemented as a <code>flow::async::Single_thread_task_loop U</code>. Then, e.g.:</p><ul>
<li>In thread U: <code>async_request(M, false, H)</code>: sends <code>M</code>; async-calls <code>H(I)</code> when response <code>I</code> to <code>M</code> arrives.</li>
<li>In (unspecified thread): <code>H(I)</code> fires. Your <code>H()</code> body: <code>U.post([I = std::move(I)]() { handle_i(std::move(I)); })</code>.</li>
<li>Actual handling of <code>I</code> occurs in your <code>void handle_i(...::Msg_in_ptr&amp;&amp;) { ... }</code>. <code>handle_i(){}</code> can be written with the assumption execution is back in thread U, same as the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> call that triggered all this (asynchronously).</li>
</ul>
<p >This is <em>not</em> a requirement. It is entirely conceivable one would want to piggy-back onto our internal unspecified thread (or threads &ndash; formally speaking &ndash; but the guarantee is handlers are called non-concurrently, so in most senses one can treat it as a single thread). However please be mindful:</p><ul>
<li>If your handler code is "heavy," then you may slow down internal <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> processing on a number of layers (though, only relevant to <code>*this</code>).</li>
<li>Let's say we call your own thread, thread U, and the internal/unspecified <code>*this</code> thread where it invokes handlers, thread W. Then it is your responsibility to ensure you do not call a non-<code>const</code> method of <code>*this</code> concurrently to another <code>*this</code> method. If you choose a design where you make such calls both from thread U and thread W, you must protect <code>*this</code> access with a mutex or other mechanism.</li>
</ul>
<h3>Pipe-hosing error semantics</h3>
<p >The underlying <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>, which every <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> takes over in the first place at construction, can fail &ndash; encounter a pipe-hosing error. Briefly speaking, a <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> out-pipe can &ndash; depending on the actual low-level transport involved &ndash; be hosed while the in-pipe(s) remain unaffected; and indeed when a <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> internally consists of 2 bidirectional pipes, it is even possible for 1 out-pipe to be hosed, while the other is not. (The same holds of in-pipes.) However, these details strongly depend on the actual low-level transports involved. To simplify error handling, these details are hidden away and normalized to the following straightforward behavior.</p>
<p >As noted before, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> models a single bidirectional full-duplex pipe of discrete messages. The out-pipe is controlled simply: call <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>, or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> to send a message, synchronously, non-blockingly (if not <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>). The in-pipe takes in all messages as soon as they arrive on the <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> "wire"; they may be queued inside or immediately (or later) emitted, but this is not relevant to error handling.</p>
<p >The entire bidirectional pipe is either not-hosed, or it is hosed (forever). A pipe-hosing condition, indicated by a truthy <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a>, occurs (if it occurs at all) exactly once. (Note: Receiving the <code><a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a></code>-level graceful-close message &ndash; <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297" title="All possible errors returned (via Error_code arguments) by ipc::transport functions/methods outside o...">transport::error::Code</a>:: S_RECEIVES_FINISHED_CANNOT_RECEIVE &ndash; is not "special" &ndash; it is also a pipe-hosing error.) When it occurs, it is immediately emitted to the <code>*this</code> user. There are 2 possible ways this can occur (again: only 1 of these can occur per <code>*this</code>):</p><ul>
<li>Triggered by <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>, or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>: Then that method shall emit the truthy <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> directly/synchronously via out-arg or exception.</li>
<li>Triggered spuriously in the background via incoming-direction processing: Then it shall be emitted via the on-error handler registered by the user. (If this occurs during <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>, then it shall be emitted via <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>, not via on-error handler.)<ul>
<li>To receive any in-messages, you must call <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a33b4785c212ad88d8322fcc2f4369351" title="Permanently memorizes the incoming-direction on-error handler, thus authorizing the emission of any i...">start()</a> which takes the mandatory on-error handler as arg. Until then, any lower-level in-traffic shall be safely queued inside the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a>. Still, it is best to call <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a33b4785c212ad88d8322fcc2f4369351" title="Permanently memorizes the incoming-direction on-error handler, thus authorizing the emission of any i...">start()</a> early, to avoid RAM backup and such (informally speaking).</li>
</ul>
</li>
</ul>
<p >After the pipe-hosing error is emitted, via exactly 1 of the above methods, further API calls on <code>*this</code> shall no-op and return <code>false</code> or a null value.</p>
<p >Lastly, there is <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a>. See its doc header. TL;DR: Although the pipe is hosed at the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> level once a pipe-hosing <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> is emitted, it is still a good idea to execute <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> and only destroy <code>*this</code> once the async-handler passed to it has fired. (Though, if <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> (et al) emitted the truthy <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a>, there is no point: <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> will no-op.)</p>
<p >Informal recommendations:</p><ul>
<li>Recall that we recommend any event handling, from within an in-message handler or any other handler, be immediately off-loaded onto a user worker thread. (In particular you may not call <code>*this</code> APIs from these handlers.)</li>
<li>When such a user-thread handler, or other user-thread function, detects the emitted truthy <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> (from on-error handler, or via <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>, or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> emitting it synchronously), mark <code>*this</code>, somehow, as hosed (e.g., via a flag or saved truthy <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a>).</li>
<li>When about to do work on <code>*this</code>, check that flag or mark, so as to be aware <code>*this</code> is hosed and shutting down &ndash; and no-op instead of trying to call whatever API. Though, it may be viable to simply count on the fact <code>*this</code> APIs shall all (except <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a>) no-op and return <code>false</code> or null in that case anyway.</li>
<li>Lastly, recommend then calling <code>async_end_sending(F)</code>; and in <code>F()</code> destroy <code>*this</code> finally.</li>
<li>If you have 1 thread (e.g., via <code>flow::async::Single_thread_task_loop</code>) dedicated to processing <code>*this</code>, then this is particularly straightforward; no need to synchronize on <code>*this</code> and/or the <code>*this</code>-is-hosed flag/mark.</li>
</ul>
<h3>Lifecycle of an out-message</h3>
<p ><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> represents the message payload. It is a data structure instance &ndash; nothing more. Its outer shell sits wherever it is instantiated; typically either on the stack or in regular heap. It allocates space for the the serialization mutated by its <code>.body_root()</code> capnp <code>Builder</code> based on the <code>Struct_builder_config</code> type chosen at compile-time. (If you use <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a394e0f9cfa5f9bd4ba9ee17d3d54a8b3" title="Creates/returns empty out-message, optionally also holding a native handle, to mutate and later send(...">create_msg()</a>, this light-weight object &ndash; essentially a few scalars &ndash; is supplied to the <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__out.html" title="A structured out-message suitable to be sent via struc::Channel::send() (et al).">Msg_out</a></code> ctor for you. Otherwise you have to construct one directly and pass-in a <code>Builder_config</code> or <code>Builder</code> of the same type.) This builder <em>engine</em> determines where this internal bulk &ndash; the serialization backing &ndash; lives. For the rest of this discussion let us assume it is <code>shm::classic::Builder::Config</code> (or jemalloc equivalent); meaning the engine is zero-copy-enabling, for high perf and other benefits, and therefore allocates backing buffer(s) in SHM.</p>
<p ><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a>, therefore, is similar to a container backed by a SHM-allocating allocator. It continues to take RAM resources, and the serialization continues to be accessible, on all ends until <em>both</em> of the following occur:</p><ul>
<li>The <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> is destroyed.</li>
<li>Every <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae1f4b316eaeb7ed520a84d9e21e21063" title="A ref-counted handle to Msg_in.">Msg_in_ptr</a> obtained in <em>any</em> opposing <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> to have received it (via <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a>, and response-accepting handlers), after it had been <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a>ed (et al) there, is destroyed &ndash; along with all derived <code>Msg_in_ptr</code>s. (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae1f4b316eaeb7ed520a84d9e21e21063" title="A ref-counted handle to Msg_in.">Msg_in_ptr</a> is <code>shared_ptr&lt;<a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__in.html" title="A structured in-message instance suitable as received and emittable (to user) by struc::Channel.">Msg_in</a>&gt;</code>.)</li>
</ul>
<p >Suppose you create a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> it. At this point there is "virtual" <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165" title="Encapsulation of any in-message instance received by a *this of this type.">Msg_in</a> in existence: the underlying serialization will not be destroyed yet, even if <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> is. Normally the opposing <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> will be used to receive the message, in a real <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165" title="Encapsulation of any in-message instance received by a *this of this type.">Msg_in</a>, via an aforementioned in-message handler. If this does not occur, the message leaks until the containing SHM arena is cleaned-up. (If you use <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> to manage SHM arena(s), which is the normal scenario, then <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> will take care of this for you. See <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> documentation, starting with the namespace doc header.)</p>
<p >Suppose in your application, at this point, you will never again write to the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> further (modify it). You may freely <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> the same <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> again. You may send it through a different <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> or the same one. You may do so at will. You may receive it, obviously, at will as well. Note, however, that <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165" title="Encapsulation of any in-message instance received by a *this of this type.">Msg_in</a> is not fully symmetrical to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a>: It represents not the container but rather the in-message <em>instance</em>: that particular time you received a message, with a handle to the payload controlled by the original <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a>. So for one <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a>, there may be 2+ <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__in.html" title="A structured in-message instance suitable as received and emittable (to user) by struc::Channel.">Msg_in</a></code>s in existence, across various processes to have received it. If one process has received it 2x, then there are potentially 2 <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__in.html" title="A structured in-message instance suitable as received and emittable (to user) by struc::Channel.">Msg_in</a></code>s in existence in that process. The original <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> and each <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165" title="Encapsulation of any in-message instance received by a *this of this type.">Msg_in</a> each contributes 1 to the cross-process ref-count.</p>
<p >Lastly suppose all the same is true, except that you would like to continue modifying the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> post-<code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a></code>. This is allowed. However, this must be done with care. Of course there is the matter of synchronization as usual: Behavior is undefined if one reads a message while the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> is being mutated in the original process. While it is conceivable one could use an outside synchronization mechanism for this &ndash; an interprocess mutex for example &ndash; informally we expect the best way is to use your <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> messaging protocol. In particular it make sense to avoid any modification of a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> until one has received a response to any <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> of it, with the guarantee that the module receiving that <em>particular</em> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165" title="Encapsulation of any in-message instance received by a *this of this type.">Msg_in</a> in the opposing process shall not further read its contents after issuing the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> for that response.</p>
<p >Lastly suppose <code>Struct_builder_config</code> is <em>not</em> SHM-based; e.g. <a class="el" href="structipc_1_1transport_1_1struc_1_1Heap__fixed__builder_1_1Config.html" title="Implements Struct_builder::Config sub-concept.">Heap_fixed_builder::Config</a>. In that case, simply, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> is the original message container backed by an in-local-heap serialization; and every <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165" title="Encapsulation of any in-message instance received by a *this of this type.">Msg_in</a> emitted by a receive-handler is a <em>copy</em>, also backed by an in-local-to-receiver-heap serialization. While <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> can certainly be <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a>ed repeatedly, and modified in-between, this simply has no effect on any resulting <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__in.html" title="A structured in-message instance suitable as received and emittable (to user) by struc::Channel.">Msg_in</a></code>s, as they are copies.</p>
<h3>Log-in</h3>
<p >Internally, each out-message is supplied by <code>*this</code> with a <em>session token</em>. In regular operation, every out-message's session token is the same value through the lifetime of a <code>*this</code>. Every in-message must also contain that same session token value. If an in-message arrives with an unexpected session token value, it is a pipe-hosing error. (The rationale for this is beyond the scope of discussion here; it is a safety feature.) This all happens internally.</p>
<p >In regular operation, at <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> construction time, the constant session token value must be supplied as a ctor argument. This session token must not be nil. While, formally speaking, any non-nil value will do &ndash; provided the same one is given to the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> on the other end &ndash; correct use (in terms of safety) is to provide a properly generated unique token &ndash; on both sides. Where to get this value, though? Answer:</p>
<p >Before constructing any regular-operation <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a></code>s, in a given session between two processes A and B, one shall first construct <em>one</em> special-purpose <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>, called the <em>session master channel</em>, and wrap it in a special-purpose <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> on each side. This is the 2nd ctor form, the one without a <code>session_token</code> arg; one side must pass the value <code>is_server = true</code>; the other conversely <code>is_server = false</code>.</p>
<p >This special channel is not yet in logged-in phase; it is in logging-in-as-client phase on 1 side and logging-in-as-server phase on the other side. The two <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a></code>s must then undergo a rigid, but short, sequence of steps to get to the logged-in phase (at which point the session master channel enters its own regular-operation phase; the purpose of that channel from that point on is unspecified here &ndash; but read on).</p>
<p >Namely: the client peer must create a message as normal (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a394e0f9cfa5f9bd4ba9ee17d3d54a8b3" title="Creates/returns empty out-message, optionally also holding a native handle, to mutate and later send(...">create_msg()</a> or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> construction), fill out the returned out-message as desired, and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> it. The server peer conversely must invoke <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a0054bbf18bc769b2a5b95f249e672c0a" title="In log-in phase as server only: Registers the expectation of up to 1 log-in request in-message whose ...">expect_log_in_request()</a>, exactly once, handle the incoming request by filling out a response out-message, and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> that (response-supplying form is mandatory).</p><ul>
<li>The server peer <code>*this</code> enters logged-in (regular-operation) phase upon <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a></code>ing the log-in response. Did you invoke <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> successfully? Congrats: you're in regular-operation.</li>
<li>The client peer <code>*this</code> enters logged-in (regular-operation) phase upon receiving that log-in response Did your handler for the response get fired? Congrats: you're in regular-operation.</li>
</ul>
<p >While this mechanism is fairly general, and hopefully reasonably easy to operate, in practice most users will not need to ever do so themselves. Instead: On the server side, establish a <code>Server_session</code> (see <a class="el" href="classipc_1_1session_1_1Session__server.html" title="To be instantiated typically once in a given process, an object of this type asynchronously listens f...">session::Session_server</a>). On the client side, establish a <code>Client_session</code>. They will operate an adequate session master channel internally. <code>Server_session</code> and <code>Client_session</code> shall then each reach their PEER state, at which point they each satisfy the formal <a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">session::Session</a> concept (see <a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">session::Session</a> doc header). Now, <a class="el" href="classipc_1_1session_1_1Session.html#abc6ce8839621c1e19db80ccd4f2e2589" title="In PEER state: Returns the (non-nil) logged-in session token to be used for any struc::Channels one m...">session::Session::session_token()</a> shall return the uniquely generated session token. This value shall be passed to all subsequent <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a></code>s in the session, into their ctors (possibly via internal delegation). These subsequent <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a></code>s do not need a log-in phase and are immediately in regular-operation.</p>
<p >Therefore, the only time a user must worry about session tokens at all is when creating a regular-operation <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a>, and even then only if no tag-form <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> ctor is applicable. In that case:</p><ul>
<li>Access <a class="el" href="classipc_1_1session_1_1Session.html#abc6ce8839621c1e19db80ccd4f2e2589" title="In PEER state: Returns the (non-nil) logged-in session token to be used for any struc::Channels one m...">session::Session::session_token()</a>.</li>
<li>Pass the result into <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> ctor on each side.</li>
</ul>
<p >Incidentally, <code>Session</code> (as implemented by <code>Server_session</code>, <code>Client_session</code>, and variants) can also easily open new <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">Channel</a></code>s. Internally they do so by leveraging various features of <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> as applied to the <em>one</em> (per process A-B session) session master channel. Each <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">Channel</a></code> obtained this way can then be fed (upgraded) into a new <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a>, if indeed structured messaging is desired for that <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>. The information in this paragraph is, formally speaking, outside the purview of <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> API, but I mention it here for context. For more detail see <a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">session::Session</a> (and its impls <a class="el" href="namespaceipc_1_1session.html#ab01d5bce0ab2f3435ca9dd88d27609dc" title="A vanilla Server_session with no optional capabilities.">session::Server_session</a>, <a class="el" href="namespaceipc_1_1session.html#a77d8fda00e1e17f595a6a5d4c44375e7" title="A vanilla Client_session with no optional capabilities.">session::Client_session</a> and variants).</p>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000024">Todo:</a></b></dt><dd><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> should probably be made move-constructible and move-assignable. No concept requires this, unlike with many other classes and class templates in <a class="el" href="namespaceipc.html" title="Catch-all namespace for the Flow-IPC project: A library/API in modern C++17 providing high-performanc...">ipc</a>, so it is less essential; but both for consistency and usability it would be good. It would also make some APIs possible that currently would require the user to explicitly wrap this class in a <code>unique_ptr</code>. For example, imagine a <code>Session::Structured_channel Session::structured_channel_upgrade(Channel_obj&amp;&amp; channel, ...)</code> that constructs a suitably-typed <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a>, subsuming the raw <code>channel</code> just opened in that <a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">session::Session</a>, and returns that guy. Currently it would need to return <code>unique_ptr&lt;Session::Structured_channel&gt;</code> or something.</dd></dl>
<h3>Implementation overview (threads U, W)</h3>
<p ><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> sits atop several layers of concepts and objects implementing them: from the raw transports (<a class="el" href="namespaceipc_1_1transport_1_1asio__local__stream__socket.html" title="Additional (versus boost.asio) APIs for advanced work with local stream (Unix domain) sockets includi...">transport::asio_local_stream_socket</a> namespace, <a class="el" href="classipc_1_1transport_1_1Persistent__mq__handle.html" title="A documentation-only concept defining the behavior of an object representing a light-weight handle to...">Persistent_mq_handle</a> concept and impls); to the component <a class="el" href="classipc_1_1transport_1_1Blob__sender.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order sending ...">Blob_sender</a>, <a class="el" href="classipc_1_1transport_1_1Blob__receiver.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order receivin...">Blob_receiver</a>, <a class="el" href="classipc_1_1transport_1_1Native__handle__sender.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order sending ...">Native_handle_sender</a>, <a class="el" href="classipc_1_1transport_1_1Native__handle__receiver.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order receivin...">Native_handle_receiver</a> impls; to the <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a>) bundling them together; and lastly &ndash; and most immediately relevantly &ndash; to the <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html" title="sync_io-pattern counterpart to async-I/O-pattern transport::struc::Channel.">struc::sync_io::Channel</a> core. (The latter is aliased as <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f" title="Useful for generic programming, the sync_io-pattern counterpart to *this type.">struc::Channel::Sync_io_obj</a>.)</p>
<p >In implementing <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a>, then, we already rely on much logic that is abstracted-away; we only need to "decorate" their work by, essentially, some pre- and post-processing &ndash; to provide, specifically, the features explicitly outlined above publicly ("What does struc::Channel add, broadly speaking, that
transport::Channel does not already have?").</p>
<p >Perf, in particular low latency, is essential for this work-horse class template. For performance &ndash; or perhaps more accurately for most direct/deterministic flow control/thread structure &ndash; we use <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code> objects throughout; our <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f" title="Useful for generic programming, the sync_io-pattern counterpart to *this type.">Sync_io_obj</a> core (<code>m_sync_io</code>) and the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> subsumed by it create no handler-invoking threads. We, however, are ourselves an async-I/O-pattern object, and therefore essentially by definition of how that pattern works we start a worker thread W in which to (1) perform all asynchronously-delayed (i.e., contingent on event async-waits) work of all the aforementioned layers below us (helpfully encapsulated in <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f" title="Useful for generic programming, the sync_io-pattern counterpart to *this type.">Sync_io_obj</a> <code>m_sync_io</code>); and (2) invoke user-supplied completion handlers.</p>
<p >This thread W (<code>m_worker</code>) is the only async-worker thread. Everything else is (to reiterate) <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code>-pattern.</p>
<p >Thread U is (as per usual) the term of the user's calling thread (as usual they may of course use 2+ threads if desired; however on a given <code>*this</code> all such calls must be non-concurrent... so as usual we call it thread U, as if it is one thread). We do allow transmission APIs to be invoked from within completion handlers of ours own other transmission APIs (e.g., <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a></code> or <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a></code> directly within <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a></code> handler). (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>, being blocking, is the exception.)</p>
<p >This is a familiar setup &ndash; similar to, say, <a class="el" href="classipc_1_1transport_1_1Native__socket__stream.html" title="Implements both Native_handle_sender and Native_handle_receiver concepts by using a stream-oriented U...">transport::Native_socket_stream</a>. I will immediately note, however, that we do not make any allowances for concurrent execution of receive-op APIs and send-op APIs; in our case almost all outgoing-direction APIs touch data structures in common with incoming-direction APIs &ndash; such as <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> modifying expected-in-message <code>m_rcv_*</code> stuff.</p>
<p >Since there are 2 threads, U and W, with async-processing in the latter potentially occurring concurrently with API calls in the former, there's a big fat mutex <code>m_mutex</code> locked around most code. That said thread contention is unlikely in most use cases. (Details omitted here.)</p>
<h3>Implementation</h3>
<p >Unlike in the past, when <code>*this</code> template was monolithic, now it is split into the core functionality in <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html" title="sync_io-pattern counterpart to async-I/O-pattern transport::struc::Channel.">sync_io::Channel</a> (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f" title="Useful for generic programming, the sync_io-pattern counterpart to *this type.">Sync_io_obj</a> <code>m_sync_io</code>) and the (relatively limited) logic necessary on top of this to adapt that into the async-I/O pattern, wherein user handlers fire from thread W, and any necessary internal async ops occur automatically in thread W without user participation.</p>
<p >Therefore the really complicated stuff is abstracted away in the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f" title="Useful for generic programming, the sync_io-pattern counterpart to *this type.">Sync_io_obj</a>. The adapting logic is simple enough to be understandable by reading the code and inline comments, especially on the data members. </p>
<dl class="tparams"><dt>Template Parameters</dt><dd>
  <table class="tparams">
    <tr><td class="paramname">Channel_obj</td><td>An instance of <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> class template. See <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> doc header. It must have <code>Channel_obj::S_IS_SYNC_IO_OBJ == true</code>. Reminder: the template params to <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> template (along with certain documented requirements on how to use its API when initializing it before feeding it to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> ctor) determine the number and nature of underlying transport pipes of the channel. <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> will work with anything you specify, as long as it results in a <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code>-core-bearing <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> object in PEER state fed to <code>*this</code> ctor. </td></tr>
    <tr><td class="paramname">Message_body</td><td>The capnp-generated class for the capnp-<code>struct</code> describing the schema of messages you intend to transmit over this channel. (Therefore, in particular, <code>Message_body::Builder</code> and <code>Message_body::Reader</code> shall be capnp-generated classes as well.) The contents of this capnp-<code>struct</code> are arbitrary &ndash; whatever suits one's purpose &ndash; except for the following requirement: It must contain a top-level anon capnp-<code>union</code>. <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a> shall therefore be the enumeration of the possible active value of this capnp-<code>union</code>. This union conceptually corresponds to the different types of messages one might transmit over the channel. </td></tr>
    <tr><td class="paramname">Struct_builder_config</td><td>A type satisfying the concept <a class="el" href="structipc_1_1transport_1_1struc_1_1Struct__builder_1_1Config.html" title="Copy-ctible, copy-assignable, default-ctible type – informally, cheaply copyable and likely an aggreg...">Struct_builder::Config</a>, with the additional requirement that each <code>flow::util::Blob B</code> emitted by <code>Struct_builder_config::Builder::emit_serialization()</code> satisfies the following condition: <code>B.size() &lt;= M</code>, where <code>M</code> is the lower of <code>Owned_channel::send_blob_max_size()</code>, <code>Owned_channel::send_meta_blob_max_size()</code>, for the applicable 1-2 pipes in <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a>. An object of this type is passed to ctor. This determines how, internally, <code>*this</code> shall transform structured out-messages provided by the user into binary blobs sent via the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a>. This Struct_builder_config must match the opposing peer's choice of Struct_reader_config. E.g., if this is <a class="el" href="structipc_1_1transport_1_1struc_1_1Heap__fixed__builder_1_1Config.html" title="Implements Struct_builder::Config sub-concept.">Heap_fixed_builder::Config</a>, then the other guy's thingie is <a class="el" href="structipc_1_1transport_1_1struc_1_1Heap__reader_1_1Config.html" title="Implements Struct_reader::Config sub-concept.">Heap_reader::Config</a>. In practice it is usually best to use a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> alias (as of this writing Channel_via_heap, <a class="el" href="namespaceipc_1_1transport_1_1struc_1_1shm_1_1classic.html#ac543b500a85f556564e592cbbefb6185" title="Convenience alias: Use this when constructing a struc::Channel with tag Channel_base::S_SERIALIZE_VIA...">shm::classic::Channel</a>, <a class="el" href="namespaceipc_1_1transport_1_1struc_1_1shm_1_1arena__lend_1_1jemalloc.html#ab68a69ad42d97d754f4e77c8cadd3a5e" title="Convenience alias: Use this when constructing a struc::Channel with tag Channel_base::S_SERIALIZE_VIA...">shm::arena_lend::jemalloc::Channel</a>) and accordingly to use one of the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel__base.html" title="Channel base that contains non-parameterized public items such as tag types and constants.">Channel_base</a> tags: <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel__base.html#ab0eb05b5fb52364c99868a8535aaf26e" title="The sole value of the tag type Serialize_via_heap.">Channel_base::S_SERIALIZE_VIA_HEAP</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel__base.html#af732121649271d1368a2fb637917ce7b" title="The sole value of the tag type Serialize_via_app_shm.">Channel_base::S_SERIALIZE_VIA_APP_SHM</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel__base.html#a9bdb94c1ba4fac92fbbd0f843e8525ba" title="The sole value of the tag type Serialize_via_session_shm.">Channel_base::S_SERIALIZE_VIA_SESSION_SHM</a>. See the documentation on the latter 3 for useful suggestions. </td></tr>
    <tr><td class="paramname">Struct_reader_config</td><td>A type satisfying the concept <a class="el" href="structipc_1_1transport_1_1struc_1_1Struct__reader_1_1Config.html" title="Analogous to Struct_builder::Config but for deserialization.">Struct_reader::Config</a>. An object of this type is passed to ctor. This determines how, internally, <code>*this</code> shall transform unstructured in-blobs received from the other peer over the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> into structured in-messages emitted to the user. This Struct_reader_config must match the opposing peer's choice of Struct_builder_config. See <code>Struct_builder_config</code> notes just above. </td></tr>
  </table>
  </dd>
</dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00586">586</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>
</div><h2 class="groupheader">Member Typedef Documentation</h2>
<a id="ae01d976c856e82b4370e9e69e6128cff" name="ae01d976c856e82b4370e9e69e6128cff"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ae01d976c856e82b4370e9e69e6128cff">&#9670;&nbsp;</a></span>Async_io_obj</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Async_io_obj =  <a class="el" href="classipc_1_1transport_1_1Null__peer.html">Null_peer</a></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>You may disregard. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00597">597</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a346752b515926a2938ed2adb9de92b1e" name="a346752b515926a2938ed2adb9de92b1e"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a346752b515926a2938ed2adb9de92b1e">&#9670;&nbsp;</a></span>Builder_config</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Builder_config =  typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a8a59bbc3c6a7191b316b23661d8ba6e3">Sync_io_obj::Builder_config</a></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Short-hand for the builder engine type. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00603">603</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="af0d9dcd9c3ccf8e064f0cca69b30ea25" name="af0d9dcd9c3ccf8e064f0cca69b30ea25"></a>
<h2 class="memtitle"><span class="permalink"><a href="#af0d9dcd9c3ccf8e064f0cca69b30ea25">&#9670;&nbsp;</a></span>Lock_guard</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Lock_guard =  flow::util::Lock_guard&lt;<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ade399eda73424def3da0dd67596d2cff">Mutex</a>&gt;</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Short-hand for <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ade399eda73424def3da0dd67596d2cff" title="Short-hand for m_mutex type.">Mutex</a> lock. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01348">1348</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a27a273ed7e1aca34b721fea22c869a41" name="a27a273ed7e1aca34b721fea22c869a41"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a27a273ed7e1aca34b721fea22c869a41">&#9670;&nbsp;</a></span>Msg_body</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Msg_body =  typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a34e183c252390f369f121074772c14c4">Sync_io_obj::Msg_body</a></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Short-hand for the <code>Message_body</code> template param, this is the capnp message schema transmissible over <code>*this</code>. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00608">608</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a4d4995b27b7a6944fbcceee7657f6413" name="a4d4995b27b7a6944fbcceee7657f6413"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a4d4995b27b7a6944fbcceee7657f6413">&#9670;&nbsp;</a></span>msg_id_out_t</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::msg_id_out_t =  typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a9b5d17887c9ad1e37081bf4ae4a70e65">Sync_io_obj::msg_id_out_t</a></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Short-hand for convenience for the same thing in non-parameterized base <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel__base.html" title="Channel base that contains non-parameterized public items such as tag types and constants.">Channel_base</a>. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00649">649</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a05d1cd2fc6a81a39c50a24322fb5c165" name="a05d1cd2fc6a81a39c50a24322fb5c165"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a05d1cd2fc6a81a39c50a24322fb5c165">&#9670;&nbsp;</a></span>Msg_in</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Msg_in =  typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#ac3da0ac1306b63c9e38c47b8c31e3cd2">Sync_io_obj::Msg_in</a></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Encapsulation of any in-message <em>instance</em> received by a <code>*this</code> of this type. </p>
<dl class="section see"><dt>See also</dt><dd>"Lifecycle of an out-message" section of this class's doc header.</dd>
<dd>
<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae1f4b316eaeb7ed520a84d9e21e21063" title="A ref-counted handle to Msg_in.">Msg_in_ptr</a> </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00639">639</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="ae1f4b316eaeb7ed520a84d9e21e21063" name="ae1f4b316eaeb7ed520a84d9e21e21063"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ae1f4b316eaeb7ed520a84d9e21e21063">&#9670;&nbsp;</a></span>Msg_in_ptr</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Msg_in_ptr =  typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#acde2b3866547a30958035203d9d89928">Sync_io_obj::Msg_in_ptr</a></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>A ref-counted handle to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165" title="Encapsulation of any in-message instance received by a *this of this type.">Msg_in</a>. </p>
<p >Generally one obtains a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165" title="Encapsulation of any in-message instance received by a *this of this type.">Msg_in</a> via a handle thereto via handler passed to event registration APIs such as <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a> or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>; then one accesses its contents via capnp-generated accessors on <a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__in.html#a56fa38feb9c907ae3f0f1a6ff16dd32f" title="The Body root capnp-generated accessor object.">Msg_in::body_root()</a>. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00646">646</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a860cc99a701576879ebb5a1db58153cc" name="a860cc99a701576879ebb5a1db58153cc"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a860cc99a701576879ebb5a1db58153cc">&#9670;&nbsp;</a></span>Msg_out</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Msg_out =  typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a83fb4462a8d4045bdb56b694bf80393c">Sync_io_obj::Msg_out</a></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Encapsulation of any out-message <em>payload</em> sent or meant to be sent via <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> (et al) by a <code>*this</code> of this type. </p>
<p >A <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> is container-like, in that there is only one of these regardless of how many times one has sent it &ndash; even in other <code>*this</code>es of the same <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> concrete type.</p>
<dl class="section see"><dt>See also</dt><dd>"Lifecycle of an out-message" section of this class's doc header. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00630">630</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a9a0382aa663c177f2a38b576d06b251e" name="a9a0382aa663c177f2a38b576d06b251e"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a9a0382aa663c177f2a38b576d06b251e">&#9670;&nbsp;</a></span>Msg_which</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Msg_which =  typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a1572a1b1cb4a72ea57f7841a5e78759b">Sync_io_obj::Msg_which</a></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Short-hand for the <code>Message_body</code> top-level anon capnp-<code>union</code> enumeration. </p>
<p >This important type determines the type of in-message or out-message the (remote or local, respectively) user chose. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00615">615</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="ac2a3a80151886bec41f3fc3a8880e384" name="ac2a3a80151886bec41f3fc3a8880e384"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ac2a3a80151886bec41f3fc3a8880e384">&#9670;&nbsp;</a></span>Msg_which_in</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Msg_which_in =  typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#aa40c3ec3f45cdfea9360f7f35b9ade3c">Sync_io_obj::Msg_which_in</a></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Stylistic nicety, indicating that a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a> applies to an in-message rather than an out-message. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00618">618</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a4cc597a9ff8f460f5a773005f0a05805" name="a4cc597a9ff8f460f5a773005f0a05805"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a4cc597a9ff8f460f5a773005f0a05805">&#9670;&nbsp;</a></span>Msg_which_out</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Msg_which_out =  typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a7a731cdae5217ed9e867fb80c1fb0fd9">Sync_io_obj::Msg_which_out</a></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Stylistic nicety, indicating that a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a> applies to an out-message rather than an in-message. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00621">621</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="ade399eda73424def3da0dd67596d2cff" name="ade399eda73424def3da0dd67596d2cff"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ade399eda73424def3da0dd67596d2cff">&#9670;&nbsp;</a></span>Mutex</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Mutex =  flow::util::Mutex_non_recursive</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Short-hand for <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a01c90903e715ebcf64d8b5ea0d114bc0" title="Mutex protecting the in-message/out-message state in *this.">m_mutex</a> type. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01345">1345</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a1df9dd26651017e61d7701bf3af42260" name="a1df9dd26651017e61d7701bf3af42260"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a1df9dd26651017e61d7701bf3af42260">&#9670;&nbsp;</a></span>On_msg_func</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::On_msg_func =  <a class="el" href="namespaceipc.html#aa455c7f045059736578ca275fc1a851f">Function</a>&lt;void (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae1f4b316eaeb7ed520a84d9e21e21063">Msg_in_ptr</a>&amp;&amp; msg)&gt;</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Concrete type corresponding to <code>On_msg_handler</code> template param: in-message handler. </p>
<p >We at times wrap that guy in a <code>shared_ptr</code> to minimize having to copy actual function objects &ndash; we can instead copy/move <code>shared_ptr&lt;On_msg_func&gt;</code> instead. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01407">1407</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a4a0188052c15cab70d712f41b0e74ba7" name="a4a0188052c15cab70d712f41b0e74ba7"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a4a0188052c15cab70d712f41b0e74ba7">&#9670;&nbsp;</a></span>Owned_channel</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Owned_channel =  typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a4abac89dbd4d26c79b7915990f751a76">Sync_io_obj::Owned_channel</a></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Short-hand for the <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> type passed into ctor and returned by <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a1d0225edcfe5f000f26787d5fa5f6821" title="Access to immutable transport::Channel moved-into *this at construction.">owned_channel()</a>. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00600">600</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="ad3ff78f00b7f230562d713ec6cf8499c" name="ad3ff78f00b7f230562d713ec6cf8499c"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ad3ff78f00b7f230562d713ec6cf8499c">&#9670;&nbsp;</a></span>Reader_config</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Reader_config =  typename <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a14a7166b2f8c117ce6ddafe943d036fa">Sync_io_obj::Reader_config</a></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Short-hand for the reader engine type. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00605">605</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a9426e8e562dd4c9ea1bc1f69f47bb99f" name="a9426e8e562dd4c9ea1bc1f69f47bb99f"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a9426e8e562dd4c9ea1bc1f69f47bb99f">&#9670;&nbsp;</a></span>Sync_io_obj</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Sync_io_obj =  <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html">sync_io::Channel</a>&lt;Channel_obj, Message_body, Struct_builder_config, Struct_reader_config&gt;</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Useful for generic programming, the <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code>-pattern counterpart to <code>*this</code> type. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l00594">594</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<h2 class="groupheader">Constructor &amp; Destructor Documentation</h2>
<a id="abe73bfa20ca0207ac8aa63d26d54de83" name="abe73bfa20ca0207ac8aa63d26d54de83"></a>
<h2 class="memtitle"><span class="permalink"><a href="#abe73bfa20ca0207ac8aa63d26d54de83">&#9670;&nbsp;</a></span>Channel()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<div class="memtemplate">
template&lt;typename... Ctor_args&gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Channel </td>
          <td>(</td>
          <td class="paramtype">flow::log::Logger *&#160;</td>
          <td class="paramname"><em>logger_ptr</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">Channel_obj &amp;&amp;&#160;</td>
          <td class="paramname"><em>channel</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">Ctor_args &amp;&amp;...&#160;</td>
          <td class="paramname"><em>ctor_args</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">explicit</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>All explicit constructors: signatures match exactly those of <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html" title="sync_io-pattern counterpart to async-I/O-pattern transport::struc::Channel.">struc::sync_io::Channel</a> (a/k/a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f" title="Useful for generic programming, the sync_io-pattern counterpart to *this type.">Sync_io_obj</a>). </p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html" title="sync_io-pattern counterpart to async-I/O-pattern transport::struc::Channel.">struc::sync_io::Channel</a> ctor doc headers. They're important!</dd></dl>
<dl class="tparams"><dt>Template Parameters</dt><dd>
  <table class="tparams">
    <tr><td class="paramname">Ctor_args</td><td>Arguments per above. </td></tr>
  </table>
  </dd>
</dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">logger_ptr</td><td>See above. </td></tr>
    <tr><td class="paramname">channel</td><td>See above. </td></tr>
    <tr><td class="paramname">ctor_args</td><td>See above. </td></tr>
  </table>
  </dd>
</dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01595">1595</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

<p class="reference">References <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01464">ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::m_mutex</a>, <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01561">ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::m_sync_io</a>, <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01543">ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::m_worker</a>, <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2sync__io_2channel_8hpp_source.html#l02383">ipc::transport::struc::sync_io::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::replace_event_wait_handles()</a>, and <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2sync__io_2channel_8hpp_source.html#l02390">ipc::transport::struc::sync_io::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::start_ops()</a>.</p>
<div class="dynheader">
Here is the call graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classipc_1_1transport_1_1struc_1_1Channel_abe73bfa20ca0207ac8aa63d26d54de83_cgraph.svg" width="371" height="120"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>

</div>
</div>
<a id="abf9f4ae00258efb7a5d868a087658ffe" name="abf9f4ae00258efb7a5d868a087658ffe"></a>
<h2 class="memtitle"><span class="permalink"><a href="#abf9f4ae00258efb7a5d868a087658ffe">&#9670;&nbsp;</a></span>~Channel()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::~<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">Channel</a></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Invokes the destructor on the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a>. </p>
<p >In particular:</p><ul>
<li>If the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> async-handler is pending, it shall fire with <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297afe29343445a7bf167cc186a44bd2c6ed" title="Async completion handler is being called prematurely, because underlying object is shutting down,...">transport::error::Code::S_OBJECT_SHUTDOWN_ABORTED_COMPLETION_HANDLER</a>, and the dtor shall return only once it has finished executing.</li>
<li>No other handler from <code>*this</code> shall fire. (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> does not &ndash; outside of <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a>, a <code><a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a></code>-level method &ndash; follow the boost.asio-like one-off <code>async_*()</code> model.)</li>
</ul>
<p >Reminder: It is recommended, before invoking this destructor, to:</p><ul>
<li>Call <code>async_end_sending(F)</code>.</li>
<li>Invoke this destructor once <code>F()</code> fires.</li>
</ul>
<p >See discussion in <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> doc header or shorter version in class doc header. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01669">1669</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

<p class="reference">References <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297afe29343445a7bf167cc186a44bd2c6ed">ipc::transport::error::S_OBJECT_SHUTDOWN_ABORTED_COMPLETION_HANDLER</a>.</p>

</div>
</div>
<h2 class="groupheader">Member Function Documentation</h2>
<a id="ab08057edd9832d94ea0e18a17c42200a" name="ab08057edd9832d94ea0e18a17c42200a"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ab08057edd9832d94ea0e18a17c42200a">&#9670;&nbsp;</a></span>async_end_sending()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<div class="memtemplate">
template&lt;typename Task_err &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::async_end_sending </td>
          <td>(</td>
          <td class="paramtype">Task_err &amp;&amp;&#160;</td>
          <td class="paramname"><em>on_done_func</em></td><td>)</td>
          <td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Operating at the unstructured layer, executes a graceful-close send by forwarding to the async <a class="el" href="classipc_1_1transport_1_1Channel.html#a37fcdfdbefd8ee7e374b0596782ad128" title="Performs hndl_snd()-&gt; and/or blob_snd()-&gt; same method, synthesizing completion handlers into one if a...">transport::Channel::async_end_sending()</a> on the owned <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a>. </p>
<p >Reminder: Assuming not called after <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> again: it queues a graceful-close after any other messages sent previously; and executes <code>on_done_func(E)</code> once that graceful-close is actually sent into the low-level transport (then <code>E</code> is falsy), or a transport error is encountered at any point, including in the past (then <code>E</code> is truthy). Because the owned channel's lifetime is equal to that of <code>*this</code>, if <code>on_done_func()</code> has not executed when <code>*this</code> dtor runs, it will be executed at that time with the usual <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297afe29343445a7bf167cc186a44bd2c6ed" title="Async completion handler is being called prematurely, because underlying object is shutting down,...">transport::error::Code::S_OBJECT_SHUTDOWN_ABORTED_COMPLETION_HANDLER</a>.</p>
<p ><code>on_done_func()</code> shall, as usual, execute from an unspecified thread that is not among the user calling thread(s); and it shall not execute concurrently to any other handler invoked by <code>*this</code>.</p>
<p >Formally &ndash; that is all it does, period. Informally it is important to understand the relationship between this call and the rest of the API which operates at the structured layer, particularly insofar as it relates to the error semantics on that layer. (Please read the class doc header first.)</p>
<h3>Why and when to use this</h3>
<p >The short answer as to when and how to use it: While optional, the best practice is: If you are done using the channel (for any reason, whether due to error &ndash; as reported via the error handler &ndash; but especially <em>without</em> any error), you should call <code>async_end_sending(F)</code>, asynchronously wait for <code>F()</code> to execute, and in or after <code>F()</code> destroy <code>*this</code> to free resources.</p>
<p >The long answer which hopefully explains the short answer is as follows. It's long, but the short answer is sufficient arguably. So read if desired.</p>
<p >Let us first consider the case where no <code>*this</code> error has occurred so far, meaning the <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a33b4785c212ad88d8322fcc2f4369351" title="Permanently memorizes the incoming-direction on-error handler, thus authorizing the emission of any i...">start()</a></code>-passed error handler has not been invoked, and you no longer need the channel. The immediate thought might be, simply, this means a graceful-close is in order as a matter of decent behavior, which is fair enough; although it would not be wrong to implement your own application-layer message exchange for this (by adding these into your <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a27a273ed7e1aca34b721fea22c869a41" title="Short-hand for the Message_body template param, this is the capnp message schema transmissible over *...">Msg_body</a> capnp schema and sending it like any other message). However that is <em>not</em>, I (ygoldfel) contend, the main reason <code>async_end_sending(F)</code> is a good idea in this context. That real reason: <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> (et al), externally, behaves as-if it is both synchronous and non-blocking yet cannot yield a would-block condition. However, per <a class="el" href="classipc_1_1transport_1_1Native__handle__sender.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order sending ...">Native_handle_sender</a> and <a class="el" href="classipc_1_1transport_1_1Blob__sender.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order sending ...">Blob_sender</a> concept model docs, <code>send*()</code> actually may (though this should be rare in practice) be internally asynchronous, in that it may encounter a would-block low-level transport condition (e.g., MQ full, or local-stream-socket would-block), save a copy of the payload, and only succeed in passing it to the out-wire later. <code>async_end_sending(F)</code> can and should be viewed as the async <em>out-flush</em>: it ensures all the queued sends have truly succeeded &ndash; or a transport error triggered &ndash; and only <em>then</em> executes <code>F()</code> asynchronously. Hence by waiting until <code>F()</code> before destroying <code>*this</code> you will have ensured that all those care-free synchronous non-blocking sends have truly gone out; therefore <code>*this</code> can be destroyed without accidentally cutting off the end of the conversation.</p>
<p >Next let's talk about the error cases. There are roughly 2 as of this writing. One, a "soft" non-channel-hosing situation can occur, namely information about a local or remote application-protocol error might trigger a handler like those set by <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab7cd0bed6392cb155f9ee21071c5226b" title="Registers the handler to invoke when a response in-message arrives, but no response-expectation has b...">set_unexpected_response_handler()</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9ec7ff431b51fec8aacacccb23a2d4e3" title="Registers the handler to invoke when the remote peer encounters the condition that would fire the rem...">set_remote_unexpected_response_handler()</a>. While this may well indicate a serious problem to the user, <code>*this</code> does not consider it that way. It is up to the user to decide what to do when such a "soft" handler executes. They could do nothing: conceivably they coded in a loose way and consider this not an issue. Or they could consider this worth ending the conversation. In that case, the situation is not <em>too</em> different from the non-error case discussed above. Want to end <code>*this</code>? Flush any sends via <code>async_end_sending(F)</code>, then after <code>F()</code> destroy <code>*this</code>. At least this features less entropy and is better, or at least not worse, than abruptly destroying the <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> peer (and possibly whole channel).</p>
<p >Lastly: Two, an actual fatal error may occur. This is where there is some subtlety, due to the subtle difference between the unstructured layer (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> operation) and structured layer (the protocol in <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> on top of that). Suppose a channel-hosing error occurs: the <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a33b4785c212ad88d8322fcc2f4369351" title="Permanently memorizes the incoming-direction on-error handler, thus authorizing the emission of any i...">start()</a></code>-passed error handler <em>has</em> been invoked; by definition this means <code>*this</code> can transmit no more <em>structured</em> messages in either direction; and in fact all further APIs, with the exception of <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a>, will return <code>false</code> (or similar) and no-op. However: a channel-hosing error is (this is the subtlety!) one of 2 rough types.</p><ol type="1">
<li>It might be an unstructured-layer error: the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> was trying to send or receive some blob or handle, on behalf of <code>*this</code> internal code, and it encountered a pipe-hosing error E. E was then immediately emitted by <code>*this</code> via the <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a33b4785c212ad88d8322fcc2f4369351" title="Permanently memorizes the incoming-direction on-error handler, thus authorizing the emission of any i...">start()</a></code>-passed error handler. Most public APIs from that point will no-op indicating prior pipe-hosing error.</li>
<li>It might be a structured-layer error: that is the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> is transmitting stuff fine still, but the logical contents of what has been received is corrupted or unexpected &ndash; maybe the other side misbehaved, or there's a bug somewhere, maybe auth failed for some reason. Blobs and handles could continue to be sent, but <code>*this</code> considers that bad, because the logical consistency of its world cannot be guaranteed. In this case <code>*this</code> internally generates an appropriate E (for example <a class="el" href="namespaceipc_1_1transport_1_1struc_1_1error.html#a990b9ff850cf9aaf354efdd07d86a71da2fba90660c799be216d283a3129f1f63" title="Structured channel: auth session token in in-message does not match expected value established during...">error::Code::S_STRUCT_CHANNEL_INTERNAL_PROTOCOL_BAD_AUTH</a>) and emits it via the <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a33b4785c212ad88d8322fcc2f4369351" title="Permanently memorizes the incoming-direction on-error handler, thus authorizing the emission of any i...">start()</a></code>-passed error handler. Most public APIs from that point will no-op indicating prior pipe-hosing error.</li>
</ol>
<p >Type 1 is more straightforward to think about. If a prior send emitted E due to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> layer error E, then <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> will simply emit E as well. If a prior receive emitted E similarly, then <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> may re-emit E as well or not; for <a class="el" href="classipc_1_1transport_1_1Native__socket__stream.html" title="Implements both Native_handle_sender and Native_handle_receiver concepts by using a stream-oriented U...">Native_socket_stream</a> (wherein internally there's a single local-socket connection for both directions despite being full-duplex &ndash; an error in one direction hoses the other direction) yes; for the MQs (wherein the 2 pipes are fully decoupled) no. That's not all that straightforward already.</p>
<p >Type 2 is even less straightforward. In this case <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> is fine: so <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> will yield a successful E most likely &ndash; but meanwhile <code>*this</code> is generally behaving as if it's hosed; and indeed it is &ndash; just at the higher (strucuted) layer!</p>
<p >The point of all this: It is pointless to worry about how <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a>'s emitted <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> relates to what was emitted to the <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a33b4785c212ad88d8322fcc2f4369351" title="Permanently memorizes the incoming-direction on-error handler, thus authorizing the emission of any i...">start()</a></code>-passed error handler. It may be the same thing; it may be different; and it may well even be a falsy (success) <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a>! <code>async_end_sending(F)</code> &ndash; again &ndash; accomplishes a lower-level task: it waits until any unsent messages are flushed out and then informs user via <code>F()</code>; and if this is at any stage impossible (including immediately, due to prior error) then it indicates it right then via <code>F(E)</code> as well. <em>They operate at different layers, even though their error may overlap depending on the situation.</em> Hence, you should indeed invoke <code>async_end_sending(F)</code> from or after the error handler is invoked, then destroy <code>*this</code> after <code>F()</code>.</p><ul>
<li>If <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> out-pipe is hosed anyway, this will simply get to <code>*this</code> destruction stage immediately, which is fine: it's what one would do if they decide to not mess with <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> at all.</li>
<li>If <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> out-pipe is fine (despite something else &ndash; possibly in-pipe, possibly structured protocol &ndash; being not-at-all-fine), this will in civilized fashion flush anything that might still be pending for whatever reason &ndash; and gracefully inform the other side that, at any rate, this peer does not want to talk anymore. This reduces entropy; and at worst does not help anything but does not hurt.</li>
</ul>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000027">Todo:</a></b></dt><dd>Consider adding blocking <code>struc::Channel::sync_end_sending()</code>, possibly with timeout, since <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a></code> to completion is recommended (but not required) to execute at EOL of any <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a>. The "blocking" part is good because it's convenient to not have to worry about handling completion with async semantics boiler-plate. The "timeout" part is good because it's a best-effort operation, when in a bad/slow environment, and blocking &ndash; even during deinit &ndash; would be important to avoid. For example, the <code>Session</code> impls' dtors perform this op; we don't want those to block for any significant time if at all avoidable. The reason it's a mere to-do currently is that a bug-free opposing <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> should not let would-block occur for any real length of time; so blocking is presumably unlikely. Nevertheless.</dd></dl>
<dl class="tparams"><dt>Template Parameters</dt><dd>
  <table class="tparams">
    <tr><td class="paramname">Task_err</td><td>See <a class="el" href="classipc_1_1transport_1_1Channel.html#a37fcdfdbefd8ee7e374b0596782ad128" title="Performs hndl_snd()-&gt; and/or blob_snd()-&gt; same method, synthesizing completion handlers into one if a...">transport::Channel::async_end_sending()</a>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">on_done_func</td><td>See <a class="el" href="classipc_1_1transport_1_1Channel.html#a37fcdfdbefd8ee7e374b0596782ad128" title="Performs hndl_snd()-&gt; and/or blob_snd()-&gt; same method, synthesizing completion handlers into one if a...">transport::Channel::async_end_sending()</a>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>See <a class="el" href="classipc_1_1transport_1_1Channel.html#a37fcdfdbefd8ee7e374b0596782ad128" title="Performs hndl_snd()-&gt; and/or blob_snd()-&gt; same method, synthesizing completion handlers into one if a...">transport::Channel::async_end_sending()</a>. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01761">1761</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

<p class="reference">References <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297aa667487757f9d6300f6888bac40bcc24">ipc::transport::error::S_SYNC_IO_WOULD_BLOCK</a>.</p>

</div>
</div>
<a id="a97506bcb695f22e7ca6b480bae5b2346" name="a97506bcb695f22e7ca6b480bae5b2346"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a97506bcb695f22e7ca6b480bae5b2346">&#9670;&nbsp;</a></span>async_request()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<div class="memtemplate">
template&lt;typename On_msg_handler &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::async_request </td>
          <td>(</td>
          <td class="paramtype">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc">Msg_out</a> &amp;&#160;</td>
          <td class="paramname"><em>msg</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165">Msg_in</a> *&#160;</td>
          <td class="paramname"><em>originating_msg_or_null</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4d4995b27b7a6944fbcceee7657f6413">msg_id_out_t</a> *&#160;</td>
          <td class="paramname"><em>id_unless_one_off</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">On_msg_handler &amp;&amp;&#160;</td>
          <td class="paramname"><em>on_rsp_func</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a> *&#160;</td>
          <td class="paramname"><em>err_code</em> = <code>0</code>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Identical to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> sends the out-message not as a <em>notification</em> but as a <em>request</em>, registering the expectation of 1+ response(s) to it, async-invoking the provided response handler once reponse(s) arrive(s). </p>
<p ><code>id_unless_one_off = nullptr</code> means up to exactly 1 response in-message shall be allowed, hence <code>on_rsp_func()</code> shall execute at most once; at which point the expectation shall be unregistered. <code>id_unless_one_off != nullptr</code> means responses shall be allowed (and passed to response handler) arbitrarily many times &ndash; until one calls <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a34780bd3507a571cb719ce1d59e5d56f" title="Unregisters the expectation earlier-registered with the id_unless_one_off != nullptr form of async_re...">undo_expect_responses()</a> (specifically <code>undo_expect_responses(*id_unless_one_off)</code>).</p>
<p >This variation on <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> shall no-op (and return <code>false</code>) if one of the following is true.</p><ul>
<li>Log-in phase, as a client, has not yet been completed, and <code>originating_msg_or_null</code> is non-null. Use null instead.</li>
<li>Log-in phase, as a server, has not yet been completed, and <code>originating_msg_or_null</code> is null. Use non-null instead.</li>
</ul>
<p >Further documentation of behavior shall assume this no-op condition is not the case.</p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> which sends a <em>notification</em> (same thing as here but <em>without</em> expecting response(s)). </dd></dl>
<dl class="section note"><dt>Note</dt><dd>You may use this in any phase (logged-in; or logging-in, as server or client). </dd>
<dd>
Informally: In log-in phase, as a server, it would be unorthodox to use this method: <code>msg</code> by definition must be the log-in response; and it would be unusual for the log-in response to itself be a request for another response (or even multiple). Nevertheless this <em>is</em> allowed; use cases are conceivable, and there is no reason to restrict this. However note: As discussed elsewhere, logged-in phase is reached (as a server) the moment <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> succeeds. Any further responses are irrelevant to that (but could in theory be useful for some other purpose).</dd></dl>
<p>All non-conflicting notes from <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> apply here.</p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> for properly flushing out-messages near the end of <code>*this</code> lifetime.</dd></dl>
<dl class="tparams"><dt>Template Parameters</dt><dd>
  <table class="tparams">
    <tr><td class="paramname">On_msg_handler</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">msg</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a>. </td></tr>
    <tr><td class="paramname">originating_msg_or_null</td><td>Pointer to the in-message to which this is responding. If the in-message is from another <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a>, behavior is undefined. Set to null if this message is unsolicited (not a response). </td></tr>
    <tr><td class="paramname">id_unless_one_off</td><td>See above. </td></tr>
    <tr><td class="paramname">on_rsp_func</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>. <code>on_rsp_func(M)</code> shall be invoked in the manner explained in class doc header, on receipt of message M that indicates <code>msg</code> was its originating request. (On truthy <code>id_unless_one_off</code> it may be invoked more than once, until <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a34780bd3507a571cb719ce1d59e5d56f" title="Unregisters the expectation earlier-registered with the id_unless_one_off != nullptr form of async_re...">undo_expect_responses()</a>.) </td></tr>
    <tr><td class="paramname">err_code</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a>. Note: No error is possible on account of <code>on_rsp_func</code> and <code>id_unless_one_off</code>, additions over the other overload(). </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd><code>false</code> if no-op-ing due to one of the following conditions: invoked in logging-in phase as client but <code>originating_msg_or_null</code> is non-null; invoked in logging-in phase as server but <code>originating_msg_or_null</code> is null; <code>msg</code> with-handle, but <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> has no handles pipe; an <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> was previously emitted via on-error handler or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> / <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> / <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> has already been called. <code>true</code> otherwise (but some <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> may be emitted due to send failure). </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02267">2267</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a394e0f9cfa5f9bd4ba9ee17d3d54a8b3" name="a394e0f9cfa5f9bd4ba9ee17d3d54a8b3"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a394e0f9cfa5f9bd4ba9ee17d3d54a8b3">&#9670;&nbsp;</a></span>create_msg()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc">::Msg_out</a> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::create_msg </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8">Native_handle</a> &amp;&amp;&#160;</td>
          <td class="paramname"><em>hndl_or_null</em> = <code><a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8">Native_handle</a>()</code></td><td>)</td>
          <td> const</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Creates/returns empty out-message, optionally also holding a native handle, to mutate and later <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> (et al). </p>
<p >Alternatively you may simply directly construct a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a>; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a394e0f9cfa5f9bd4ba9ee17d3d54a8b3" title="Creates/returns empty out-message, optionally also holding a native handle, to mutate and later send(...">create_msg()</a> is only syntactic sugar, since <code>*this</code> memorizes the builder engine and will pass-it-through to the aforementioned constructor.</p>
<dl class="section see"><dt>See also</dt><dd>"Lifecycle of an out-message" section of this class's doc header.</dd></dl>
<dl class="section note"><dt>Note</dt><dd>The decision as to whether the returned message is unsolicited or a response to an in-message shall be indicated at <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> (et al) time via its <code>originating_msg_or_null</code> arg.</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">hndl_or_null</td><td>The native handle to pair with the structured message; or default-cted (null) handle to pair no such thing. It becomes <code>.null()</code> &ndash; <code>*this</code> is in charge of returning it to OS at the proper time. You may use <code>dup()</code> in a Unix-like OS, if you want to keep a functioning handle (FD) locally. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>The new out-message payload, blank to start. Note <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a> is cheaply move-assignable and move-constructible (but not copyable). </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02033">2033</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a0054bbf18bc769b2a5b95f249e672c0a" name="a0054bbf18bc769b2a5b95f249e672c0a"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a0054bbf18bc769b2a5b95f249e672c0a">&#9670;&nbsp;</a></span>expect_log_in_request()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<div class="memtemplate">
template&lt;typename On_msg_handler &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::expect_log_in_request </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384">Msg_which_in</a>&#160;</td>
          <td class="paramname"><em>which</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">On_msg_handler &amp;&amp;&#160;</td>
          <td class="paramname"><em>on_log_in_req_func</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>In log-in phase as server only: Registers the expectation of up to 1 <em>log-in request</em> in-message whose <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a> equals <code>which</code>, firing the provided handler asynchronously once the <em>log-in response</em> does arrive. </p>
<p >No-op and return <code>false</code> if <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a0054bbf18bc769b2a5b95f249e672c0a" title="In log-in phase as server only: Registers the expectation of up to 1 log-in request in-message whose ...">expect_log_in_request()</a> has already been invoked, if log-in phase is not active or active in the client role, or if a prior error has hosed the owned <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>.</p>
<p >Informally the proper behavior is:</p><ol type="1">
<li>Construct in log-in-as-server phase.</li>
<li>Invoke <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a0054bbf18bc769b2a5b95f249e672c0a" title="In log-in phase as server only: Registers the expectation of up to 1 log-in request in-message whose ...">expect_log_in_request()</a>.</li>
<li>Await <code>on_log_in_req_func(X&amp;&amp;)</code> firing, where X is the log-in request.</li>
<li>After <code>on_log_in_req_func(X&amp;&amp;)</code> handler: check X for correctness (such as process identity checks). If it fails checks, destroy <code>*this</code>; else:</li>
<li>Fill out <code>X = this-&gt;<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a394e0f9cfa5f9bd4ba9ee17d3d54a8b3" title="Creates/returns empty out-message, optionally also holding a native handle, to mutate and later send(...">create_msg()</a></code> (the log-in response) as needed via <code>X-&gt;body_root()</code>.</li>
<li><code>send(X)</code>. The latter automatically moves <code>*this</code> to logged-in phase locally: the bulk of the API becomes available.</li>
</ol>
<dl class="tparams"><dt>Template Parameters</dt><dd>
  <table class="tparams">
    <tr><td class="paramname">On_msg_handler</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">which</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>. </td></tr>
    <tr><td class="paramname">on_log_in_req_func</td><td>See above. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd><code>true</code> on success; <code>false</code> due to one of the above conditions. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02048">2048</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a160a8d49624f15a2596ee7b0244584b0" name="a160a8d49624f15a2596ee7b0244584b0"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a160a8d49624f15a2596ee7b0244584b0">&#9670;&nbsp;</a></span>expect_msg()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<div class="memtemplate">
template&lt;typename On_msg_handler &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::expect_msg </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384">Msg_which_in</a>&#160;</td>
          <td class="paramname"><em>which</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">On_msg_handler &amp;&amp;&#160;</td>
          <td class="paramname"><em>on_msg_func</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Registers the expectation of up to 1 <em>notification</em> in-message whose <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a> equals <code>which</code>. </p>
<p >No-op and return <code>false</code> if <code>which</code> is already being expected, if log-in phase is not yet completed, or if a prior error has hosed the owned <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>.</p>
<p >The expectation is unregistered upon receipt of the applicable in-message (and firing it with that in-message <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae1f4b316eaeb7ed520a84d9e21e21063" title="A ref-counted handle to Msg_in.">Msg_in_ptr</a> as arg).</p>
<dl class="tparams"><dt>Template Parameters</dt><dd>
  <table class="tparams">
    <tr><td class="paramname">On_msg_handler</td><td>Handler type for in-messages; see class doc header for in-message handling signature. </td></tr>
  </table>
  </dd>
</dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">which</td><td>Top-level <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a27a273ed7e1aca34b721fea22c869a41" title="Short-hand for the Message_body template param, this is the capnp message schema transmissible over *...">Msg_body</a> union <code>which()</code> value to expect. </td></tr>
    <tr><td class="paramname">on_msg_func</td><td><code>on_msg_func(M)</code> shall be invoked in the manner explained in class doc header, on receipt of message with <code>which() == which</code>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd><code>true</code> on success; <code>false</code> due to one of the above conditions. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02041">2041</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

<p class="reference">Referenced by <a class="el" href="session__base_8hpp_source.html#l01070">ipc::session::Session_base&lt; S_MQ_TYPE_OR_NONE, S_TRANSMIT_NATIVE_HANDLES, Mdt_payload &gt;::Graceful_finisher::Graceful_finisher()</a>.</p>
<div class="dynheader">
Here is the caller graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classipc_1_1transport_1_1struc_1_1Channel_a160a8d49624f15a2596ee7b0244584b0_icgraph.svg" width="360" height="59"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>

</div>
</div>
<a id="a8ca2772b0a657cb55f140a6273e528b9" name="a8ca2772b0a657cb55f140a6273e528b9"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a8ca2772b0a657cb55f140a6273e528b9">&#9670;&nbsp;</a></span>expect_msg_impl()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<div class="memtemplate">
template&lt;bool MSG_ELSE_LOG_IN, typename On_msg_handler &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::expect_msg_impl </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384">Msg_which_in</a>&#160;</td>
          <td class="paramname"><em>which</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">On_msg_handler &amp;&amp;&#160;</td>
          <td class="paramname"><em>on_msg_func</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Implements the one-off expect-message APIs <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a0054bbf18bc769b2a5b95f249e672c0a" title="In log-in phase as server only: Registers the expectation of up to 1 log-in request in-message whose ...">expect_log_in_request()</a>. </p>
<dl class="tparams"><dt>Template Parameters</dt><dd>
  <table class="tparams">
    <tr><td class="paramname">MSG_ELSE_LOG_IN</td><td><code>true</code> if <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>, <code>false</code> is <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a0054bbf18bc769b2a5b95f249e672c0a" title="In log-in phase as server only: Registers the expectation of up to 1 log-in request in-message whose ...">expect_log_in_request()</a>. </td></tr>
    <tr><td class="paramname">On_msg_handler</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a> and buddy. </td></tr>
  </table>
  </dd>
</dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">which</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a> and buddy. </td></tr>
    <tr><td class="paramname">on_msg_func</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a> and buddy. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a> and buddy. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02055">2055</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a3376b821b129ca3847484a178e080c67" name="a3376b821b129ca3847484a178e080c67"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a3376b821b129ca3847484a178e080c67">&#9670;&nbsp;</a></span>expect_msgs()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<div class="memtemplate">
template&lt;typename On_msg_handler &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::expect_msgs </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384">Msg_which_in</a>&#160;</td>
          <td class="paramname"><em>which</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">On_msg_handler &amp;&amp;&#160;</td>
          <td class="paramname"><em>on_msg_func</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Registers the expectation of 0+ <em>notification</em> in-messages whose <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e" title="Short-hand for the Message_body top-level anon capnp-union enumeration.">Msg_which</a> equals <code>which</code>. </p>
<p >No-op and return <code>false</code> if <code>which</code> is already being expected, if log-in phase is not yet completed, or if a prior error has hosed the owned <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>.</p>
<p >The expectation is unregistered upon subsequent <code>undo_expect_msgs(which)</code>.</p>
<dl class="tparams"><dt>Template Parameters</dt><dd>
  <table class="tparams">
    <tr><td class="paramname">On_msg_handler</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">which</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>. </td></tr>
    <tr><td class="paramname">on_msg_func</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02170">2170</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a08062e4cc99347e94e9e917b382985ee" name="a08062e4cc99347e94e9e917b382985ee"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a08062e4cc99347e94e9e917b382985ee">&#9670;&nbsp;</a></span>heap_fixed_builder_config()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="structipc_1_1transport_1_1struc_1_1Heap__fixed__builder_1_1Config.html">Heap_fixed_builder::Config</a> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::heap_fixed_builder_config </td>
          <td>(</td>
          <td class="paramtype">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7">Owned_channel</a> &amp;&#160;</td>
          <td class="paramname"><em>channel</em></td><td>)</td>
          <td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">static</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Utility for use when <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a346752b515926a2938ed2adb9de92b1e" title="Short-hand for the builder engine type.">Builder_config</a> template param is <a class="el" href="structipc_1_1transport_1_1struc_1_1Heap__fixed__builder_1_1Config.html" title="Implements Struct_builder::Config sub-concept.">Heap_fixed_builder::Config</a>, this returns such a <code>Config</code> constructed with the most efficient yet safe values. </p>
<p >The resulting <a class="el" href="structipc_1_1transport_1_1struc_1_1Heap__fixed__builder_1_1Config.html" title="Implements Struct_builder::Config sub-concept.">Heap_fixed_builder::Config</a>, and the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> <code>channel</code>, can then be safely passed to the future <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a>'s non-tag ctor form.</p>
<h3>Do not use this unless necessary</h3>
<p >It is only necessary for advanced purposes, particularly if you choose to use a non-tag ctor form. See the 1st non-tag ctor's doc header for when that might be. Long story short, it is typically easier and sufficient to use the <a class="el" href="structipc_1_1transport_1_1struc_1_1Channel__base_1_1Serialize__via__heap.html" title="Tag type for ctor selection: Backing memory for serialization comes from fixed-size segment allocatio...">Channel_base::Serialize_via_heap</a> tag ctor.</p>
<h3>What about <a class="el" href="structipc_1_1transport_1_1struc_1_1Heap__reader_1_1Config.html" title="Implements Struct_reader::Config sub-concept.">Heap_reader::Config</a> counterpart?</h3>
<p >See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a629c06957e1c5fac96d62473f7e18966" title="Deserializing counterpart to heap_fixed_builder_config().">heap_reader_config()</a>.</p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">channel</td><td>The channel you plan to pass as <code>channel</code> into <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> ctor. Note <code>channel.get_logger()</code> is supplied as the <code>Logger</code> to the returned <code>Config</code>. Behavior is undefined (assertion may trip) if <code>channel</code> is not <a class="el" href="classipc_1_1transport_1_1Channel.html#a43c79955b3ad0eab347550b4263523ec" title="Returns true if and only if the required init_blob_pipe() and init_native_handle_pipe() calls have be...">transport::Channel::initialized()</a>. Behavior is undefined if <code>channel</code> is not in PEER state. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01957">1957</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a629c06957e1c5fac96d62473f7e18966" name="a629c06957e1c5fac96d62473f7e18966"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a629c06957e1c5fac96d62473f7e18966">&#9670;&nbsp;</a></span>heap_reader_config()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="structipc_1_1transport_1_1struc_1_1Heap__reader_1_1Config.html">Heap_reader::Config</a> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::heap_reader_config </td>
          <td>(</td>
          <td class="paramtype">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7">Owned_channel</a> &amp;&#160;</td>
          <td class="paramname"><em>channel</em></td><td>)</td>
          <td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">static</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Deserializing counterpart to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a08062e4cc99347e94e9e917b382985ee" title="Utility for use when Builder_config template param is Heap_fixed_builder::Config, this returns such a...">heap_fixed_builder_config()</a>. </p>
<p >It is mostly provided for consistency, as it simply returns <code><a class="el" href="structipc_1_1transport_1_1struc_1_1Heap__reader_1_1Config.html" title="Implements Struct_reader::Config sub-concept.">Heap_reader::Config</a>(channel.get_logger())</code>.</p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">channel</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a08062e4cc99347e94e9e917b382985ee" title="Utility for use when Builder_config template param is Heap_fixed_builder::Config, this returns such a...">heap_fixed_builder_config()</a>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02002">2002</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a1d0225edcfe5f000f26787d5fa5f6821" name="a1d0225edcfe5f000f26787d5fa5f6821"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a1d0225edcfe5f000f26787d5fa5f6821">&#9670;&nbsp;</a></span>owned_channel()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7">::Owned_channel</a> &amp; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::owned_channel</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Access to immutable <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> moved-into <code>*this</code> at construction. </p>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02600">2600</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="af9130e43dc985fca4a41f19581048b51" name="af9130e43dc985fca4a41f19581048b51"></a>
<h2 class="memtitle"><span class="permalink"><a href="#af9130e43dc985fca4a41f19581048b51">&#9670;&nbsp;</a></span>owned_channel_mutable()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7">::Owned_channel</a> * <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::owned_channel_mutable</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Access to mutable <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> moved-into <code>*this</code> at construction. </p>
<p >Formally only the following non-<code>const</code> methods of the returned pointee may be accessed:</p><ul>
<li><a class="el" href="classipc_1_1transport_1_1Channel.html#a290395d720167759bfa1eda1e86bf123" title="Performs hndl_snd()-&gt; and/or blob_snd()-&gt; same method, returning true if all (1-2) invoked methods re...">transport::Channel::auto_ping()</a>;</li>
<li><a class="el" href="classipc_1_1transport_1_1Channel.html#abf25364b49b9fdd3ba4b1541b3a50356" title="Performs hndl_rcv()-&gt; and/or blob_rcv()-&gt; same method, returning true if all (1-2) invoked methods re...">transport::Channel::idle_timer_run()</a>.</li>
</ul>
<p >Informally: those are both safe and potentially useful. Since <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> is <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code>-core-bearing, to invoke either of those directly on the <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">Channel</a></code> <em>before</em> subsuming it into <code>*this</code> ctor, one would have to do <code>Channel::start_*_ops()</code>; but <code>*this</code> ctor requires a fresh <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> without such setup having been performed. Catch-22! However, with the availability of <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#af9130e43dc985fca4a41f19581048b51" title="Access to mutable transport::Channel moved-into *this at construction.">owned_channel_mutable()</a>, one can simply call them via <code>this-&gt;owned_channel_mutable-&gt;...()</code> and move on.</p>
<p >Informally: any other use = at your own risk. It may interfere with our operations =&gt; undefined behavior.</p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a>.</dd></dl>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000026">Todo:</a></b></dt><dd>Consider adding <code>struc::Channel::auto_ping()</code> and <code>struc::Channel::idle_timer_run()</code> and, for safety, removing <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#af9130e43dc985fca4a41f19581048b51" title="Access to mutable transport::Channel moved-into *this at construction.">struc::Channel::owned_channel_mutable()</a>.</dd></dl>
<dl class="section return"><dt>Returns</dt><dd>See above. Not null. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02607">2607</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="ae645cb58ad9ea6374970f1f32c5da448" name="ae645cb58ad9ea6374970f1f32c5da448"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ae645cb58ad9ea6374970f1f32c5da448">&#9670;&nbsp;</a></span>send()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::send </td>
          <td>(</td>
          <td class="paramtype">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc">Msg_out</a> &amp;&#160;</td>
          <td class="paramname"><em>msg</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165">Msg_in</a> *&#160;</td>
          <td class="paramname"><em>originating_msg_or_null</em> = <code>0</code>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a> *&#160;</td>
          <td class="paramname"><em>err_code</em> = <code>0</code>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>In the synchronous/non-blocking manner of <a class="el" href="classipc_1_1transport_1_1Blob__sender.html#a776b55ae93e65592b90c3943ca99e948" title="In PEER state: Synchronously, non-blockingly sends one discrete message, reliably and in-order,...">Blob_sender::send_blob()</a> or <a class="el" href="classipc_1_1transport_1_1Native__handle__sender.html#ac96b0aa01c286d525f9dcfa6dacc4220" title="In PEER state: Synchronously, non-blockingly sends one discrete message, reliably/in-order,...">Native_handle_sender::send_native_handle()</a> sends the given message to the opposing peer, as a <em>notification</em> (without expecting response). </p>
<p >The message may contain a <a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8" title="Convenience alias for the commonly used type util::Native_handle.">Native_handle</a>.</p>
<p ><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> shall no-op (and return <code>false</code>) if one of the following is true.</p><ul>
<li>Log-in phase, as a client, has not yet been completed. Use the other form of <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> instead, as a log-in response (to the log-in request <code>msg</code>) is required.</li>
<li>Log-in phase, as a server, has not yet been completed, and <code>originating_msg_or_null</code> is null. Use non-null instead.</li>
</ul>
<p >Further documentation of behavior shall assume this no-op condition is not the case.</p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> overload which sends a <em>request</em> (same thing as here but <em>with</em> expecting response(s)).</dd></dl>
<dl class="section note"><dt>Note</dt><dd>You may use this in logged-in phase; or in logging-in phase, as a server.</dd></dl>
<h3>Send mechanics (applies also to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>)</h3>
<p >The purpose of this important method is hopefully clear. That it's, essentially, a wrapper for one of the aforementioned <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> methods is also probably obvious. However its error-reporting semantics are somewhat different from <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> and the <code><a class="el" href="classipc_1_1transport_1_1Blob__sender.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order sending ...">Blob_sender</a></code>/<code><a class="el" href="classipc_1_1transport_1_1Native__handle__sender.html" title="A documentation-only concept defining the behavior of an object capable of reliably/in-order sending ...">Native_handle_sender</a></code> concept(s) it implements. Long story short, it reports errors similarly to the core <a class="el" href="classipc_1_1transport_1_1Blob__sender.html#a776b55ae93e65592b90c3943ca99e948" title="In PEER state: Synchronously, non-blockingly sends one discrete message, reliably and in-order,...">Blob_sender::send_blob()</a> or <a class="el" href="classipc_1_1transport_1_1Native__handle__sender.html#ac96b0aa01c286d525f9dcfa6dacc4220" title="In PEER state: Synchronously, non-blockingly sends one discrete message, reliably/in-order,...">Native_handle_sender::send_native_handle()</a> with the following differences:</p><ul>
<li>If <code>msg</code> contains a <a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8" title="Convenience alias for the commonly used type util::Native_handle.">Native_handle</a>, but <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> has no native-handles pipe: no-op, return <code>false</code>.</li>
<li>If called after <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a>: no-op, return <code>false</code>.</li>
<li>If called after a background receive or preceding <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> / <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> / <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> emitted error: no-op, return <code>false</code>.</li>
<li>Otherwise it'll attempt the core <code>send_*()</code> and return <code>true</code>.<ul>
<li>If that is successful, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> is successful.</li>
<li>If not &ndash; if it emitted error E &ndash; then <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> emits error E.<ul>
<li>And <code>*this</code> shall be considered hosed for any subsequent transmission.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3>In more detail (applies also to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>)</h3>
<p >Here is what the method does, ignoring logged-in phase checks and potential change inside.</p><ol type="1">
<li>If <code>msg</code> contains a <a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8" title="Convenience alias for the commonly used type util::Native_handle.">Native_handle</a>, but <a class="el" href="classipc_1_1transport_1_1Channel.html#a634da813ea03c07d8360a738eca002c4" title="Useful for generic programming: true if and only if types imply only the blobs pipe is enabled.">Channel::S_HAS_BLOB_PIPE_ONLY</a> is <code>true</code>, then returns <code>false</code> and otherwise no-ops. This is a misuse of the chosen <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> as configured: a handles pipe is required to send handles. Else:</li>
<li>Checks whether the pipe is hosed by a preceding error (which would have been reported via the on-error handler registered by user on <code>*this</code>; or by the previous <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a></code>/etc. synchronously, if that's what discovered the pipe is hosed instead). If so returns <code>false</code> and otherwise no-ops. Else: (Note the previously discovered/emitted <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> is not re-emitted this time.) Else:</li>
<li>If you've called <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> already: Returns <code>false</code> and otherwise no-ops. Else:</li>
<li>Invokes either <code>Owned_channel::send_blob()</code> or <code>Owned_channel::send_native_handle()</code> 1+ times. (If <a class="el" href="classipc_1_1transport_1_1Channel.html#a634da813ea03c07d8360a738eca002c4" title="Useful for generic programming: true if and only if types imply only the blobs pipe is enabled.">Channel::S_HAS_BLOB_PIPE_ONLY</a>: the former. If <a class="el" href="classipc_1_1transport_1_1Channel.html#a717bffc2086ccf834bc7a1137c1127eb" title="Useful for generic programming: true if and only if types imply only the handles pipe is enabled.">Channel::S_HAS_NATIVE_HANDLE_PIPE_ONLY</a>: the latter, even if <code>msg</code> stores no <a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8" title="Convenience alias for the commonly used type util::Native_handle.">Native_handle</a> (it's not required to send a handle). If <a class="el" href="classipc_1_1transport_1_1Channel.html#a85184d886cee9b4a0d0e7b67796a238b" title="Useful for generic programming: true if and only if types imply both blobs and handles pipes are enab...">Channel::S_HAS_2_PIPES</a>: the latter or the former depending on whether <code>msg</code> stores a <a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8" title="Convenience alias for the commonly used type util::Native_handle.">Native_handle</a>.) This determines the possible <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> emitted; see doc header for the chosen sender concept impls for <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a>. However:<ul>
<li>Note: <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297a42d41c622e92e9053177ba73e75633fe" title="Will not send message: local user already ended sending via API marking this.">transport::error::Code::S_SENDS_FINISHED_CANNOT_SEND</a> shall not be emitted; instead <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> will return <code>false</code> as noted above.</li>
<li>Note: Since we are in charge, internally, of invoking the low-level <code>send_*()</code> method, we shall ensure <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297ac416e988563e44bf15fc6a81743eef53" title="User called an API with 1 or more arguments against the API spec.">transport::error::Code::S_INVALID_ARGUMENT</a> is not a possibility.</li>
<li>Serialization errors are also possible (can be thought of similarly to <code>send_*()</code> failing).</li>
</ul>
</li>
<li>If such a call emits an error, the present method shall forward (emit) that error (but return <code>true</code>). Moreover the pipe shall be considered hosed:<ul>
<li>The triggering <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> will <em>not</em> be emitted to user via on-error handler registered on <code>*this</code>, because it will be emitted to the caller synchronously here by <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a>.</li>
<li>No futher on-in-message user handlers (such as from <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>) shall fire.</li>
<li>Any future transmission API calls will no-op indicating this in various ways:<ul>
<li><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a>, <code>set_*_handler()</code> shall return <code>false</code>;</li>
<li><code>create_*()</code> shall return null;</li>
<li><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> shall return <code>false</code> (as noted above).</li>
</ul>
</li>
</ul>
</li>
<li>Otherwise, cool. It shall return <code>true</code> and not emit a truthy <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a>.</li>
</ol>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> for properly flushing out-messages near the end of <code>*this</code> lifetime.</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">msg</td><td>The out-message, which may or may not store a <a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8" title="Convenience alias for the commonly used type util::Native_handle.">Native_handle</a>. </td></tr>
    <tr><td class="paramname">originating_msg_or_null</td><td>Pointer to the in-message to which this is responding. If the in-message is from another <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a>, behavior is undefined. Set to null if this message is unsolicited (not a response). </td></tr>
    <tr><td class="paramname">err_code</td><td>See <code>flow::Error_code</code> docs for error reporting semantics. <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> generated: See above. Not <code>INVALID_ARGUMENT</code>, not <code>SENDS_FINISHED_CANNOT_SEND</code>. Also possible: serialization-failed errors (at least <a class="el" href="namespaceipc_1_1transport_1_1struc_1_1error.html#a990b9ff850cf9aaf354efdd07d86a71da3deddc950bfa6d35ae03c9494eec15a6" title="Structured message serialization (e.g., when sending over channel): A user-mutated datum (e....">error::Code::S_INTERNAL_ERROR_SERIALIZE_LEAF_TOO_BIG</a> unless <code>Struct_builder_config</code> is SHM-based). </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd><code>false</code> if no-op-ing due to one of the following conditions: invoked in logging-in phase as client; invoked in logging-in phase as server but <code>originating_msg_or_null</code> is null; <code>msg</code> with-handle, but <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> has no handles pipe; an <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> was previously emitted via on-error handler or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> / <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> / <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> has already been called. <code>true</code> otherwise (but some <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> may be emitted due to send failure). </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02251">2251</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a9a540a274df3bc7da8fc35ed2a2c1e57" name="a9a540a274df3bc7da8fc35ed2a2c1e57"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a9a540a274df3bc7da8fc35ed2a2c1e57">&#9670;&nbsp;</a></span>session_token()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">const <a class="el" href="namespaceipc_1_1transport_1_1struc.html#a6751c05fb6582a34c7c47ac470c4a48b">Session_token</a> &amp; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::session_token</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Returns the (non-nil) logged-in session token; or nil if not in logged-in phase, or if a prior error has hosed the owned <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>. </p>
<p >Informally: If <code>*this</code> is the session master channel, then: Outside of, perhaps, logging/reporting, it should not be necessary to call this.</p>
<dl class="section return"><dt>Returns</dt><dd>See above. Note: The reference returned is always one of 2: a certain unspecified internal item, or to <a class="el" href="namespaceipc_1_1transport_1_1struc.html#ad556d20a2aa2d52b83c7afb73951d47d" title="A value for which .is_nil() is true.">transport::struc::NULL_SESSION_TOKEN</a>. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02614">2614</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a9ec7ff431b51fec8aacacccb23a2d4e3" name="a9ec7ff431b51fec8aacacccb23a2d4e3"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a9ec7ff431b51fec8aacacccb23a2d4e3">&#9670;&nbsp;</a></span>set_remote_unexpected_response_handler()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<div class="memtemplate">
template&lt;typename On_remote_unexpected_response_handler &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::set_remote_unexpected_response_handler </td>
          <td>(</td>
          <td class="paramtype">On_remote_unexpected_response_handler &amp;&amp;&#160;</td>
          <td class="paramname"><em>on_func</em></td><td>)</td>
          <td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Registers the handler to invoke when the <em>remote</em> peer encounters the condition that would fire the <em>remote</em> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab7cd0bed6392cb155f9ee21071c5226b" title="Registers the handler to invoke when a response in-message arrives, but no response-expectation has b...">set_unexpected_response_handler()</a> handler (regardless of whether one is indeed remotely registered), causing that peer to inform <code>*this</code> of that event in the background. </p>
<p >No-op and return <code>false</code> if a handler is already registered.</p>
<p >Note that, while this and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a1d5415ad72e5758f15fd49d2faabb3e0" title="Undoes set_remote_unexpected_response_handler().">unset_remote_unexpected_response_handler()</a> can be invoked during logging-in phase, <code>on_func()</code> won't fire until the logged-in phase. To be clear: Nothing is "deferred"; that condition simply cannot occur until the logged-in phase. An unexpected response during the highly rigid logging-in phase is treated as a channel-hosing (fatal) condition.</p>
<dl class="tparams"><dt>Template Parameters</dt><dd>
  <table class="tparams">
    <tr><td class="paramname">On_remote_unexpected_response_handler</td><td>Functor type with signature compatible with <code>void F(msg_id_out_t, std::string&amp;&amp;)</code>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">on_func</td><td><code>on_func(M, B, S)</code> shall be fired, where <code>M</code> is the offending out-message's <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4d4995b27b7a6944fbcceee7657f6413" title="Short-hand for convenience for the same thing in non-parameterized base Channel_base.">msg_id_out_t</a> (for logging/reporting only); <code>S</code> a (movable) <code>string</code> containing brief abitrary info suitable for logging about the message; and <code>B</code> is <code>true</code> if this is a response to a timed-out <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> on the opposing side, <code>false</code> otherwise. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd><code>true</code> on success; <code>false</code> due to one of the above conditions. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02561">2561</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="ab7cd0bed6392cb155f9ee21071c5226b" name="ab7cd0bed6392cb155f9ee21071c5226b"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ab7cd0bed6392cb155f9ee21071c5226b">&#9670;&nbsp;</a></span>set_unexpected_response_handler()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<div class="memtemplate">
template&lt;typename On_unexpected_response_handler &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::set_unexpected_response_handler </td>
          <td>(</td>
          <td class="paramtype">On_unexpected_response_handler &amp;&amp;&#160;</td>
          <td class="paramname"><em>on_func</em></td><td>)</td>
          <td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Registers the handler to invoke when a response in-message arrives, but no response-expectation has been registered (via <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>), or the one-off request had been previously satisfied with another response, or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a34780bd3507a571cb719ce1d59e5d56f" title="Unregisters the expectation earlier-registered with the id_unless_one_off != nullptr form of async_re...">undo_expect_responses()</a> has been issued for an open-ended request, or the response is to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> that has timed out. </p>
<p >No-op and return <code>false</code> if a handler is already registered.</p>
<p >Note that, regardless of whether this handler is registered: If an unsolicited response does arrive, the opposing (offending) peer shall be informed of this. See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9ec7ff431b51fec8aacacccb23a2d4e3" title="Registers the handler to invoke when the remote peer encounters the condition that would fire the rem...">set_remote_unexpected_response_handler()</a> for what that is like from their point of view.</p>
<p >Lastly note that, while this and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ad3070c369762b2f5e85555155f65bdaa" title="Undoes set_unexpected_response_handler().">unset_unexpected_response_handler()</a> can be invoked during logging-in phase, <code>on_func()</code> won't fire until the logged-in phase. To be clear: Nothing is "deferred"; that condition simply cannot occur until the logged-in phase. An unexpected response during the highly rigid logging-in phase is treated as a channel-hosing (fatal) condition.</p>
<dl class="tparams"><dt>Template Parameters</dt><dd>
  <table class="tparams">
    <tr><td class="paramname">On_unexpected_response_handler</td><td>Functor type with signature compatible with <code>void F(Msg_in_ptr&amp;&amp;)</code>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">on_func</td><td><code>on_func(M, B)</code> shall be fired, where <code>M</code> is the offending in-message; <code>B</code> is <code>true</code> if this is a response to a timed-out <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>, <code>false</code> otherwise. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd><code>true</code> on success; <code>false</code> due to one of the above conditions. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02524">2524</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a33b4785c212ad88d8322fcc2f4369351" name="a33b4785c212ad88d8322fcc2f4369351"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a33b4785c212ad88d8322fcc2f4369351">&#9670;&nbsp;</a></span>start()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<div class="memtemplate">
template&lt;typename Task_err &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::start </td>
          <td>(</td>
          <td class="paramtype">Task_err &amp;&amp;&#160;</td>
          <td class="paramname"><em>on_err_func</em></td><td>)</td>
          <td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Permanently memorizes the incoming-direction on-error handler, thus authorizing the emission of any in-messages to handlers registered via <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a>, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> (as well as related handlers <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab7cd0bed6392cb155f9ee21071c5226b" title="Registers the handler to invoke when a response in-message arrives, but no response-expectation has b...">set_unexpected_response_handler()</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9ec7ff431b51fec8aacacccb23a2d4e3" title="Registers the handler to invoke when the remote peer encounters the condition that would fire the rem...">set_remote_unexpected_response_handler()</a>). </p>
<p >Until this is invoked, any incoming lower-level traffic is nevertheless saved in this process's user RAM (in fact inside the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a>, though that's an implementation detail of sorts) to be emitted as required after <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a33b4785c212ad88d8322fcc2f4369351" title="Permanently memorizes the incoming-direction on-error handler, thus authorizing the emission of any i...">start()</a>.</p>
<dl class="tparams"><dt>Template Parameters</dt><dd>
  <table class="tparams">
    <tr><td class="paramname">Task_err</td><td>Handler type matching signature of <code>flow::async::Task_asio_err</code>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">on_err_func</td><td>The permanent on-channel-hosed error handler. See class doc header for discussion of error semantics. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd><code>true</code> on success; <code>false</code> if already <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a33b4785c212ad88d8322fcc2f4369351" title="Permanently memorizes the incoming-direction on-error handler, thus authorizing the emission of any i...">start()</a>ed, or if a prior error has hosed the owned <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a> (then no-op). </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01878">1878</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a969bc2021565c542c902fc14ff711c38" name="a969bc2021565c542c902fc14ff711c38"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a969bc2021565c542c902fc14ff711c38">&#9670;&nbsp;</a></span>struct_builder_config()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a346752b515926a2938ed2adb9de92b1e">::Builder_config</a> &amp; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::struct_builder_config</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Returns the (light-weight) <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a346752b515926a2938ed2adb9de92b1e" title="Short-hand for the builder engine type.">Builder_config</a> specified (directly or indirectly) at construction time. </p>
<p >Informally: in particular this could be used to generate a <code>Builder_config::Builder</code> to fill out manually via <a class="el" href="classipc_1_1transport_1_1struc_1_1Struct__builder.html#a9a4b9587c162f85ad4d3e0a5fad8dffb" title="Pointer to the payload Capnp_msg_builder_interface, suitable for mutation by the user.">Struct_builder::payload_msg_builder()</a> (a direct <a class="el" href="classCapnp__msg__builder__interface.html">Capnp_msg_builder_interface</a>), without yet specifying any schema, and eventually <code>move()</code> into a new <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc" title="Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...">Msg_out</a>, via the <a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__out.html" title="A structured out-message suitable to be sent via struc::Channel::send() (et al).">Msg_out</a> 2nd/advanced ctor form.</p>
<p >Tip: If you lack a <code>*this</code> from which to invoke <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a969bc2021565c542c902fc14ff711c38" title="Returns the (light-weight) Builder_config specified (directly or indirectly) at construction time.">struct_builder_config()</a>, you may be able to cheaply generate a <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a346752b515926a2938ed2adb9de92b1e" title="Short-hand for the builder engine type.">Builder_config</a> via <a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">session::Session</a> impls' methods (e.g., <a class="el" href="classipc_1_1session_1_1Session__mv.html#a107684fdd5d233549c6daac26a81a542" title="Utility that obtains a heap-based (non-zero-copy) Struct_builder::Config, constructed with the most e...">session::Session_mv::heap_fixed_builder_config()</a>, <a class="el" href="classipc_1_1session_1_1shm_1_1classic_1_1Session__mv.html#a0fbea0563835e852069cdaab506dd92c" title="Identical to session_shm_builder_config() but backed by SHM arena app_shm() instead of session_shm().">session::shm::classic::Session_mv::app_shm_builder_config()</a>, etc.).</p>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02009">2009</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="ade98da21ce433f8ba338e3139760e94a" name="ade98da21ce433f8ba338e3139760e94a"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ade98da21ce433f8ba338e3139760e94a">&#9670;&nbsp;</a></span>struct_lender_session()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Builder_config::Builder::Session &amp; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::struct_lender_session</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Returns reference to immutable <code>Builder_config::Builder::Session</code> (a light-weight value, as of this writing at most a pointer) specified (directly or indirectly) at construction time. </p>
<p >See that ctor argument's docs; the arg is also named <code>struct_lender_session</code>.</p>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02017">2017</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="ade9a8f99615d2c53de1a68989376750d" name="ade9a8f99615d2c53de1a68989376750d"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ade9a8f99615d2c53de1a68989376750d">&#9670;&nbsp;</a></span>struct_reader_config()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ad3ff78f00b7f230562d713ec6cf8499c">::Reader_config</a> &amp; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::struct_reader_config</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Deserializing counterpart to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a969bc2021565c542c902fc14ff711c38" title="Returns the (light-weight) Builder_config specified (directly or indirectly) at construction time.">struct_builder_config()</a>. </p>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02025">2025</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a18100e5af4f5111f1515ff9eef8b1f92" name="a18100e5af4f5111f1515ff9eef8b1f92"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a18100e5af4f5111f1515ff9eef8b1f92">&#9670;&nbsp;</a></span>sync_request() <span class="overload">[1/2]</span></h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae1f4b316eaeb7ed520a84d9e21e21063">::Msg_in_ptr</a> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::sync_request </td>
          <td>(</td>
          <td class="paramtype">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc">Msg_out</a> &amp;&#160;</td>
          <td class="paramname"><em>msg</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165">Msg_in</a> *&#160;</td>
          <td class="paramname"><em>originating_msg_or_null</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceipc_1_1util.html#ac66141280c3b7295a86b65209f31cc58">util::Fine_duration</a>&#160;</td>
          <td class="paramname"><em>timeout</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a> *&#160;</td>
          <td class="paramname"><em>err_code</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>A blocking (subject to timeout) operation that first acts as-if <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> was invoked in one-off-request mode; then awaits the one-off response and synchronously returns that reponse (or pipe-hosing error, or timeout error). </p>
<p >Unlike <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>, you <em>may not</em> invoke this method directly from an in-message handler or other handler. Doing so can disrupt the timeliness of delivering async results and formally results in undefined behavior.</p>
<p ><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> shall no-op (and return null without a truthy <code>Error_code</code> emitted) if:</p><ul>
<li>log-in phase has not yet been completed.</li>
</ul>
<p >Further documentation of behavior shall assume this no-op condition is not the case.</p>
<h3>Send mechanics</h3>
<p >As the first step this method invokes essentially <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>. Hence the following notes apply as they do for <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>: Long story short, it reports errors similarly to the core <a class="el" href="classipc_1_1transport_1_1Blob__sender.html#a776b55ae93e65592b90c3943ca99e948" title="In PEER state: Synchronously, non-blockingly sends one discrete message, reliably and in-order,...">Blob_sender::send_blob()</a> or <a class="el" href="classipc_1_1transport_1_1Native__handle__sender.html#ac96b0aa01c286d525f9dcfa6dacc4220" title="In PEER state: Synchronously, non-blockingly sends one discrete message, reliably/in-order,...">Native_handle_sender::send_native_handle()</a> with the following differences:</p><ul>
<li>If <code>msg</code> contains a <a class="el" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8" title="Convenience alias for the commonly used type util::Native_handle.">Native_handle</a>, but <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> has no native-handles pipe: no-op, return null with falsy <code>Error_code</code>.</li>
<li>If called after <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a>: no-op, return null with falsy <code>Error_code</code>.</li>
<li>If called after a background receive or preceding <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> / <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> / <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> emitted error: no-op, return null with falsy <code>Error_code</code>.</li>
<li>Otherwise it'll attempt the core <code>send_*()</code>.<ul>
<li>If that yields a (pipe-hosing) error, then: return null with truthy <code>Error_code</code> emitted.<ul>
<li>And <code>*this</code> shall be considered hosed for any subsequent transmission.</li>
</ul>
</li>
<li>Otherwise the method moves on to the wait phase.</li>
</ul>
</li>
</ul>
<p >The result of the wait phase shall be one of:</p><ul>
<li>non-null response returned, no truthy <code>Error_code</code> emitted (success);</li>
<li>null response returned, truthy <code>Error_code</code> that is not <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297abcfca4c2347f9d377dd2ac41c41dc027" title="A (usually user-specified) timeout period has elapsed before a blocking operation completed.">transport::error::Code::S_TIMEOUT</a> (pipe hosed during wait);</li>
<li>null response returned, <code>Error_code == S_TIMEOUT</code> (pipe is fine, but the wait timed out).</li>
</ul>
<h3>Late-response semantics</h3>
<p >If the response, or pipe-hosing error, occurs during this method's wait, then hopefully everything is clear. Now suppose it does time out and hence emits <code>Error_code</code> <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297abcfca4c2347f9d377dd2ac41c41dc027" title="A (usually user-specified) timeout period has elapsed before a blocking operation completed.">transport::error::Code::S_TIMEOUT</a>. In the background <code>*this</code> continues to await the one-off response. (Moreover it is not possible to "un-expect" it or expect a response some other way; as response expectation can only be specified at <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> time, and you've already done the latter for that out-message, and a one-off request expectation by convention cannot be undone as of this writing.)</p>
<p >If the response (after timeout) never arrives, there's nothing further to discuss.</p>
<p >Now suppose it does arrive at some point (after the timeout). It shall be handled as-if an unexpected response was received (albeit with slightly different args as noted just below). Namely:</p><ul>
<li>If <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab7cd0bed6392cb155f9ee21071c5226b" title="Registers the handler to invoke when a response in-message arrives, but no response-expectation has b...">set_unexpected_response_handler()</a> is in effect, it shall be invoked (with <code>expected_but_timed_out</code> set).</li>
<li>The opposing peer is informed of this event, and if on that side <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9ec7ff431b51fec8aacacccb23a2d4e3" title="Registers the handler to invoke when the remote peer encounters the condition that would fire the rem...">set_remote_unexpected_response_handler()</a> is in effect, the opposing-side user shall be informed via that handler (again with a flag indicating expected-but-timed-out).</li>
</ul>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">msg</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>. </td></tr>
    <tr><td class="paramname">originating_msg_or_null</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>. </td></tr>
    <tr><td class="paramname">timeout</td><td>If no appropriate response to <code>msg</code> occurs, nor does a pipe-hosing error, before this time elapses <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> shall emit <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297abcfca4c2347f9d377dd2ac41c41dc027" title="A (usually user-specified) timeout period has elapsed before a blocking operation completed.">transport::error::Code::S_TIMEOUT</a>. Note that the latter does <em>not</em> indicate the pipe has been hosed. To disable timeout you <em>must</em> use the special value <code>util::Fine_duration::max()</code>. (Rationale: Internally, a certain boost.thread API may use <code>pthread_cond_timedwait()</code> internally; this function in at least some Linuxes barfs on very high values of <code>Fine_duration</code>, as they translate into negative absolute <code>timespec</code> components. Therefore we detect the specific desire to have unlimited timeout and in that case use un-timed wait.) </td></tr>
    <tr><td class="paramname">err_code</td><td>See <code>flow::Error_code</code> docs for error reporting semantics. <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> generated: See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>. If the initial non-blocking send succeeds then other <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> possibilities include: Any pipe-hosing error that might be otherwise emitted outside a <code>sync_*()</code> due to in-traffic; and <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297abcfca4c2347f9d377dd2ac41c41dc027" title="A (usually user-specified) timeout period has elapsed before a blocking operation completed.">transport::error::Code::S_TIMEOUT</a>. Note that the latter does <em>not</em> indicate the pipe has been hosed. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>Non-null response message on success within timeout; otherwise null. If null, emitted <code>S_TIMEOUT</code> indicates non-fatal timeout; emitted other truthy <code>Error_code</code> indicates either the non-blocking send emitted pipe-hosing error, or during the wait the pipe got hosed. If null, but no <code>Error_code</code> is emitted, then the method was a non-blocking no-op for one of the reasons listed above: invoked in logging-in phase; <code>msg</code> with-handle, but <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4a0188052c15cab70d712f41b0e74ba7" title="Short-hand for the transport::Channel type passed into ctor and returned by owned_channel().">Owned_channel</a> has no handles pipe; an <a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89" title="Short-hand for flow::Error_code which is very common.">Error_code</a> was previously emitted via on-error handler or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> / <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> / <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">async_end_sending()</a> has already been called. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02321">2321</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

<p class="reference">References <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297abcfca4c2347f9d377dd2ac41c41dc027">ipc::transport::error::S_TIMEOUT</a>, and <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02259">ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::sync_request()</a>.</p>
<div class="dynheader">
Here is the call graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classipc_1_1transport_1_1struc_1_1Channel_a18100e5af4f5111f1515ff9eef8b1f92_cgraph.svg" width="368" height="47"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>

</div>
</div>
<a id="aa41aee3c76035f43833078e625e6ef78" name="aa41aee3c76035f43833078e625e6ef78"></a>
<h2 class="memtitle"><span class="permalink"><a href="#aa41aee3c76035f43833078e625e6ef78">&#9670;&nbsp;</a></span>sync_request() <span class="overload">[2/2]</span></h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae1f4b316eaeb7ed520a84d9e21e21063">::Msg_in_ptr</a> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::sync_request </td>
          <td>(</td>
          <td class="paramtype">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a860cc99a701576879ebb5a1db58153cc">Msg_out</a> &amp;&#160;</td>
          <td class="paramname"><em>msg</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a05d1cd2fc6a81a39c50a24322fb5c165">Msg_in</a> *&#160;</td>
          <td class="paramname"><em>originating_msg_or_null</em> = <code>0</code>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a> *&#160;</td>
          <td class="paramname"><em>err_code</em> = <code>0</code>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Equivalent to the other <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> overload but with no timeout; meaning it shall exit only once either the expected one-off response arrives, or a pipe-hosing error occurs. </p>
<p >Formally: this is simply <code>return sync_request(msg, originating_msg_or_null, Fine_duration::max(), err_code)</code>.</p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">msg</td><td>See other <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>. </td></tr>
    <tr><td class="paramname">originating_msg_or_null</td><td>See other <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>. </td></tr>
    <tr><td class="paramname">err_code</td><td>See other <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>See other <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02259">2259</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

<p class="reference">Referenced by <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02321">ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::sync_request()</a>.</p>
<div class="dynheader">
Here is the caller graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classipc_1_1transport_1_1struc_1_1Channel_aa41aee3c76035f43833078e625e6ef78_icgraph.svg" width="368" height="47"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>

</div>
</div>
<a id="a896bb326a58f433bade75b62f1893462" name="a896bb326a58f433bade75b62f1893462"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a896bb326a58f433bade75b62f1893462">&#9670;&nbsp;</a></span>undo_expect_msgs()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::undo_expect_msgs </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ac2a3a80151886bec41f3fc3a8880e384">Msg_which_in</a>&#160;</td>
          <td class="paramname"><em>which</em></td><td>)</td>
          <td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Unregisters the expectation earlier-registered with <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a>. </p>
<p >No-op and return <code>false</code> if <code>which</code> is not being expected via <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a>, if log-in phase is not yet completed, or if a prior error has hosed the owned <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>.</p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">which</td><td>See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67" title="Registers the expectation of 0+ notification in-messages whose Msg_which equals which.">expect_msgs()</a>. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02237">2237</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a34780bd3507a571cb719ce1d59e5d56f" name="a34780bd3507a571cb719ce1d59e5d56f"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a34780bd3507a571cb719ce1d59e5d56f">&#9670;&nbsp;</a></span>undo_expect_responses()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::undo_expect_responses </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a4d4995b27b7a6944fbcceee7657f6413">msg_id_out_t</a>&#160;</td>
          <td class="paramname"><em>originating_msg_id</em></td><td>)</td>
          <td></td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Unregisters the expectation earlier-registered with the <code>id_unless_one_off != nullptr</code> form of <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>. </p>
<p >No-op and return <code>false</code> if response to <code>originating_msg_id_or_none</code> is not being expected, if log-in phase is not yet completed, or if a prior error has hosed the owned <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">transport::Channel</a>.</p>
<dl class="section note"><dt>Note</dt><dd>It is not possible to unregister an expected response without first <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a></code>ing the thing to which such a response would pertain. If you don't want responses to a thing that's not yet sent, then don't send it.</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">originating_msg_id</td><td>The value <code>x</code> from an earlier successful <code>async_request(M, ..., &amp;x, F)</code> call, where <code>M</code> is the request out-message, F is the response handler. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd><code>true</code> on success; <code>false</code> due to one of the above conditions. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02244">2244</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a1d5415ad72e5758f15fd49d2faabb3e0" name="a1d5415ad72e5758f15fd49d2faabb3e0"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a1d5415ad72e5758f15fd49d2faabb3e0">&#9670;&nbsp;</a></span>unset_remote_unexpected_response_handler()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::unset_remote_unexpected_response_handler</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Undoes <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9ec7ff431b51fec8aacacccb23a2d4e3" title="Registers the handler to invoke when the remote peer encounters the condition that would fire the rem...">set_remote_unexpected_response_handler()</a>. </p>
<p >No-op and return <code>false</code> if no handler is registered anyway.</p>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02593">2593</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="ad3070c369762b2f5e85555155f65bdaa" name="ad3070c369762b2f5e85555155f65bdaa"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ad3070c369762b2f5e85555155f65bdaa">&#9670;&nbsp;</a></span>unset_unexpected_response_handler()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
      <table class="memname">
        <tr>
          <td class="memname">bool <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::unset_unexpected_response_handler</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Undoes <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab7cd0bed6392cb155f9ee21071c5226b" title="Registers the handler to invoke when a response in-message arrives, but no response-expectation has b...">set_unexpected_response_handler()</a>. </p>
<p >No-op and return <code>false</code> if no handler is registered anyway.</p>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l02553">2553</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<h2 class="groupheader">Friends And Related Function Documentation</h2>
<a id="a0351bb14f40312b30e6cae4927f3373b" name="a0351bb14f40312b30e6cae4927f3373b"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a0351bb14f40312b30e6cae4927f3373b">&#9670;&nbsp;</a></span>operator&lt;&lt;()</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">std::ostream &amp; operator&lt;&lt; </td>
          <td>(</td>
          <td class="paramtype">std::ostream &amp;&#160;</td>
          <td class="paramname"><em>os</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt; &amp;&#160;</td>
          <td class="paramname"><em>val</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">related</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Prints string representation of the given <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a> to the given <code>ostream</code>. </p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">os</td><td>Stream to which to write. </td></tr>
    <tr><td class="paramname">val</td><td>Object to serialize. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd><code>os</code>. </dd></dl>

</div>
</div>
<h2 class="groupheader">Member Data Documentation</h2>
<a id="a01c90903e715ebcf64d8b5ea0d114bc0" name="a01c90903e715ebcf64d8b5ea0d114bc0"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a01c90903e715ebcf64d8b5ea0d114bc0">&#9670;&nbsp;</a></span>m_mutex</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ade399eda73424def3da0dd67596d2cff">Mutex</a> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::m_mutex</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">mutable</span><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Mutex protecting the in-message/out-message state in <code>*this</code>. </p>
<p >The concurrency design is summarized in the impl section of our class doc header.</p>
<p >In thread U, we generally forward to <code>m_sync_io.same_thing()</code>; and that <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code> core may request an async-wait which we execute as a literaly <code>m_worker.async_wait(F)</code>, where <code>F()</code> &ndash; from thread W now &ndash; calls back into <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aefee55a9e754a63ce52766d6c65df92c" title="The core struc::Channel engine, implementing the sync_io pattern (see util::sync_io doc header).">m_sync_io</a> code. (Per <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code> pattern it's not a literal API call but can be considered one: it is a callback <code>(*on_active_ev_func)()</code> which executes code within <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aefee55a9e754a63ce52766d6c65df92c" title="The core struc::Channel engine, implementing the sync_io pattern (see util::sync_io doc header).">m_sync_io</a>.) Formally speaking <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html" title="sync_io-pattern counterpart to async-I/O-pattern transport::struc::Channel.">sync_io::Channel</a> forbids its APIs (including that quasi-API) being involved concurrently to each other. So we lock <code>m_mutex</code> both in thread U and within the thread-W <code>F()</code>. Informally &ndash; <code>m_sync_io</code> accesses many of the same data structured when within <code>m_sync_io.same_thing()</code> as within the async-wait handler <code>on_active_ev_func</code> it passes to us to async-wait on its behalf. For example <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0" title="Registers the expectation of up to 1 notification in-message whose Msg_which equals which.">expect_msg()</a> will register a one-off expectation; whereas receiving an unstructured message that is decoded by <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aefee55a9e754a63ce52766d6c65df92c" title="The core struc::Channel engine, implementing the sync_io pattern (see util::sync_io doc header).">m_sync_io</a> as satisfying that expectation unregister that one-off expecation in <code>m_sync_io</code>'s internal map.</p>
<h3>Perf</h3>
<p >It's similar to such discussions in <a class="el" href="classipc_1_1transport_1_1Native__socket__stream.html" title="Implements both Native_handle_sender and Native_handle_receiver concepts by using a stream-oriented U...">Native_socket_stream</a> for example. The additional items here are as follows.</p><ul>
<li>We operate potentially 2 pipes' logic in the same thread. Theoretically all else being equal handling a blob in one could delay handling a blob+possible native handle in the other and thus add latency. However that is not really how the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f" title="Useful for generic programming, the sync_io-pattern counterpart to *this type.">Sync_io_obj</a> uses them: they're really doing stuff in parallel vast majority of the time. It uses the native-handle pipe (if any!) only to transmit native handles, basically. I'll skip the pontification about why this is unlikely to create much concurrent traffic &ndash; leaving that as an exercise to the reader.</li>
<li><a class="el" href="classipc_1_1transport_1_1Native__socket__stream.html" title="Implements both Native_handle_sender and Native_handle_receiver concepts by using a stream-oriented U...">Native_socket_stream</a> allows independent &ndash; concurrent &ndash; operation of the out-pipe versus the in-pipe. E.g., <code>send_blob()</code> can run concurrently to receipt of an in-message due to <code>async_receive_blob()</code>. In our case the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f" title="Useful for generic programming, the sync_io-pattern counterpart to *this type.">Sync_io_obj</a> forbids any such thing, and indeed we use just one <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a01c90903e715ebcf64d8b5ea0d114bc0" title="Mutex protecting the in-message/out-message state in *this.">m_mutex</a>. (<a class="el" href="classipc_1_1transport_1_1Native__socket__stream.html" title="Implements both Native_handle_sender and Native_handle_receiver concepts by using a stream-oriented U...">Native_socket_stream</a> has 2, one per direction: one in Async_adapter_sender, one in Async_adapter_receiver.) We cannot really do otherwise. (Possibly <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> &ndash; not <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a> &ndash; could be factored out. Maybe look into it. Not an official to-do yet.) Does this create lock contention? It could in limited circumstances: if the user protocol is not of ping-pong fashion but rather involving heavy downloads and uploads concurrently. If this actually presents a problem in practice we could look into allowing more concurrency in <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f" title="Useful for generic programming, the sync_io-pattern counterpart to *this type.">Sync_io_obj</a> and then make use of it in <code>*this</code> by adding more mutexes and more complex logic. </li>
</ul>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01464">1464</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

<p class="reference">Referenced by <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01595">ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Channel()</a>.</p>

</div>
</div>
<a id="a5e905a57052ba370d8d2f45a361982d8" name="a5e905a57052ba370d8d2f45a361982d8"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a5e905a57052ba370d8d2f45a361982d8">&#9670;&nbsp;</a></span>m_snd_end_sending_on_done_func_or_empty</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">flow::async::Task_asio_err <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::m_snd_end_sending_on_done_func_or_empty</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Analogous to Async_adapter_sender::m_end_sending_on_done_func_or_empty. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01537">1537</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="aefee55a9e754a63ce52766d6c65df92c" name="aefee55a9e754a63ce52766d6c65df92c"></a>
<h2 class="memtitle"><span class="permalink"><a href="#aefee55a9e754a63ce52766d6c65df92c">&#9670;&nbsp;</a></span>m_sync_io</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f">Sync_io_obj</a> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::m_sync_io</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>The core <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">struc::Channel</a></code> engine, implementing the <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code> pattern (see <a class="el" href="namespaceipc_1_1util_1_1sync__io.html" title="Contains common code, as well as important explanatory documentation in the following text,...">util::sync_io</a> doc header). </p>
<p >See our class doc header for overview of how we use it (the aforementioned <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code> doc header talks about the <code><a class="el" href="namespaceipc_1_1transport_1_1struc_1_1sync__io.html" title="sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...">sync_io</a></code> pattern generally).</p>
<p >Thus, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aefee55a9e754a63ce52766d6c65df92c" title="The core struc::Channel engine, implementing the sync_io pattern (see util::sync_io doc header).">m_sync_io</a> is the synchronous engine that we use to perform our work in our asynchronous boost.asio loop running in thread W (<a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a2184077da7828589d20d7f92a31a6394" title="Thread W used to (1) fire user-provided handlers and (2) perform any async work requested by m_sync_i...">m_worker</a>) while collaborating with user thread(s) a/k/a thread U. (Recall that the user may choose to set up their own event loop/thread(s) &ndash; boost.asio-based or otherwise &ndash; and use their own equivalent of an <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aefee55a9e754a63ce52766d6c65df92c" title="The core struc::Channel engine, implementing the sync_io pattern (see util::sync_io doc header).">m_sync_io</a> instead.)</p>
<h3>Order subtlety versus <code>m_worker</code></h3>
<p >When constructing <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aefee55a9e754a63ce52766d6c65df92c" title="The core struc::Channel engine, implementing the sync_io pattern (see util::sync_io doc header).">m_sync_io</a>, we need the <code>Task_engine</code> from <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a2184077da7828589d20d7f92a31a6394" title="Thread W used to (1) fire user-provided handlers and (2) perform any async work requested by m_sync_i...">m_worker</a>. On the other hand tasks operating in <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a2184077da7828589d20d7f92a31a6394" title="Thread W used to (1) fire user-provided handlers and (2) perform any async work requested by m_sync_i...">m_worker</a> access <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aefee55a9e754a63ce52766d6c65df92c" title="The core struc::Channel engine, implementing the sync_io pattern (see util::sync_io doc header).">m_sync_io</a>. So in destructor it is important to <code>m_worker.stop()</code> explicitly, so that the latter is no longer a factor. Then when automatic destruction occurs in the opposite order of creation, the fact that <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aefee55a9e754a63ce52766d6c65df92c" title="The core struc::Channel engine, implementing the sync_io pattern (see util::sync_io doc header).">m_sync_io</a> is destroyed before <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a2184077da7828589d20d7f92a31a6394" title="Thread W used to (1) fire user-provided handlers and (2) perform any async work requested by m_sync_i...">m_worker</a> has no bad effect. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01561">1561</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

<p class="reference">Referenced by <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01595">ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Channel()</a>.</p>

</div>
</div>
<a id="ab40d8133d53135bcc41a12cc27fc8e13" name="ab40d8133d53135bcc41a12cc27fc8e13"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ab40d8133d53135bcc41a12cc27fc8e13">&#9670;&nbsp;</a></span>m_sync_op_state</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">std::optional&lt;<a class="el" href="structipc_1_1transport_1_1struc_1_1Channel_1_1Sync__op__state.html">Sync_op_state</a>&gt; <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::m_sync_op_state</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>The current state of the blocking sync-op mechanism; a <code>variant</code> that broadly describes the state as: no sync-op in progress, sync-op in progress sans result, sync-op in progress with result that has not yet been returned to user (sync-op almost over). </p>
<p >Please read on.</p>
<h3>Design of blocking sync-op mechanism</h3>
<p >A <code>sync_*()</code> operation is one that synchronously awaits in-traffic of some kind and returns some result based on the contents of this in-traffic, or an error if the pipe got hosed during the wait (in which case that error is <em>not</em> reported to the regular on-error handler, in the same way that non-blocking <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">send()</a> returns a pipe-hosing error). In addition it is subject to a (possibly infinite) user-specified timeout; if neither a successful result or an error appears by that time, then that fact is returned by <code>sync_*()</code>. After <code>sync_*()</code> returns, further in-pipe errors again go to the regular on-error handler until a <code>sync_*()</code> op starts (from thread U/W).</p>
<p >As of this writing there is only one such op: <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>. In this discussion we discuss that one specifically (while mentally considering how it might be generalized in the future; the mechanism is designed hopefully in such a way as to make it not-too-tough to extend to other <code>sync_*()</code>s; but we don't want to over-engineer this and/or confuse the reader needlessly).</p>
<p >Like all mutating APIs, <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> is never invoked concurrently with other APIs. (In addition it is explicitly not to be invoked from thread W (i.e., directly from an on-receive handler), as that would delay other handlers' execution; so it is to be invoked from thread U only.) This means that, broadly, at any point in time for <code>*this</code>, there is either no <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> running, or there is exactly one running &ndash; and no other APIs are &ndash; and moreover <code>*this</code> is safe from being destroyed.</p>
<p ><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> first performs essentially a normal non-blocking <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">async_request()</a>, and if that succeeds the blocking part begins. <code>m_sync_op_state-&gt;m_op_done_signal</code> is initialized to a promise and a future-wait (with timeout) begins in thread U. Meanwhile in the background <code>*this</code> is operating normally, handling all in-traffic. If it gets a successful result (namely a response to the particular message the nb-send sent &ndash; not some other in-traffic, which is handled normally) while such a wait is in progress in thread U, it loads the result into <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab40d8133d53135bcc41a12cc27fc8e13" title="The current state of the blocking sync-op mechanism; a variant that broadly describes the state as: n...">m_sync_op_state</a> and tickles thread U to stop waiting via <code>m_sync_op_done</code>. If it gets any pipe-hosing error, it loads that different result and similarly tickles the <code>promise</code>. If the timeout happens first, the promise is destroyed, and more importantly <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab40d8133d53135bcc41a12cc27fc8e13" title="The current state of the blocking sync-op mechanism; a variant that broadly describes the state as: n...">m_sync_op_state</a> is reset to steady state.</p>
<p >(After this, an error is handled normally through on-error handler. More interestingly, suppose a response to the formerly-expecting-response-but-now-timed-out out-message does arrive later. That out-message ID is still registered in <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aefee55a9e754a63ce52766d6c65df92c" title="The core struc::Channel engine, implementing the sync_io pattern (see util::sync_io doc header).">m_sync_io</a> as expecting a response due to a sync-op; but our special internal handler for that response detects that there is no longer a sync-request in progress, or if there is it is for a different out-message ID &ndash; so it timed out. So it is just dropped.</p>
<p >That's broadly how it works. Now specifically here are the states in the state machine. Note this machine is protected by <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a01c90903e715ebcf64d8b5ea0d114bc0" title="Mutex protecting the in-message/out-message state in *this.">m_mutex</a>.</p><ul>
<li>Null (steady state, no sync-op in progress): <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab40d8133d53135bcc41a12cc27fc8e13" title="The current state of the blocking sync-op mechanism; a variant that broadly describes the state as: n...">m_sync_op_state</a> is empty/null. <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> is not executing, or is running before or after the blocking part.</li>
<li>In-progress, no result: <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab40d8133d53135bcc41a12cc27fc8e13" title="The current state of the blocking sync-op mechanism; a variant that broadly describes the state as: n...">m_sync_op_state</a> is non-null, and its <a class="el" href="structipc_1_1transport_1_1struc_1_1Channel_1_1Sync__op__state.html#ac8c083b7c861d00e2f987a017fbe994e" title="Current state of the in-progress sync-op (as of this writing, there is only sync_request()).">Sync_op_state::m_result_if_any</a> holds <code>monostate</code>: <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> is waiting on the promise inside <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab40d8133d53135bcc41a12cc27fc8e13" title="The current state of the blocking sync-op mechanism; a variant that broadly describes the state as: n...">m_sync_op_state</a>, subject to a timeout, and no result has yet been received. (Or it is just about to enter this wait having unlocked mutex, or it had just exited it and is about to lock mutex.)<ul>
<li><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> has permanently set <a class="el" href="structipc_1_1transport_1_1struc_1_1Channel_1_1Sync__op__state.html#ad6f8e016b2abc3654e1915cc8c77c268" title="See id_t; used to check an arriving sync op result as belonging to the currently-waiting sync op.">Sync_op_state::m_id</a> to equal a unique ID and captured this in the internal response handler, so it can be checked against <code>m_id</code> later.</li>
</ul>
</li>
<li>In-progress, with result: <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab40d8133d53135bcc41a12cc27fc8e13" title="The current state of the blocking sync-op mechanism; a variant that broadly describes the state as: n...">m_sync_op_state</a> is non-null, and its <a class="el" href="structipc_1_1transport_1_1struc_1_1Channel_1_1Sync__op__state.html#ac8c083b7c861d00e2f987a017fbe994e" title="Current state of the in-progress sync-op (as of this writing, there is only sync_request()).">Sync_op_state::m_result_if_any</a> holds <em>not</em> <code>monostate</code> (but rather either a truthy <code>Error_code</code> indicating error; or else the response): <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> is as in the previous bullet. However, since the result is ready, the code (in thread W) &ndash; having detected the result condition &ndash; will, just before unlocking the mutex having set the result in <a class="el" href="structipc_1_1transport_1_1struc_1_1Channel_1_1Sync__op__state.html#ac8c083b7c861d00e2f987a017fbe994e" title="Current state of the in-progress sync-op (as of this writing, there is only sync_request()).">Sync_op_state::m_result_if_any</a>, tickle the promise, waking up the wait in <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a>.<ul>
<li>Suppose <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">sync_request()</a> wins the race by timing out first. It will then set <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab40d8133d53135bcc41a12cc27fc8e13" title="The current state of the blocking sync-op mechanism; a variant that broadly describes the state as: n...">m_sync_op_state</a> to null (and return timeout to caller, all in thread U).<ul>
<li>If an error occurs in thread W subsequently, we'll see there's no sync-op in progress and report error normally via on-error handler.</li>
<li>If response to the ID arrives, we'll see there's no sync-op in progress, or a new one is in progress but with different <code>m_id</code>, so it is a late-arrival. Then we drop it. </li>
</ul>
</li>
</ul>
</li>
</ul>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01531">1531</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="abb0ed2e666191dd85e543072077bf38b" name="abb0ed2e666191dd85e543072077bf38b"></a>
<h2 class="memtitle"><span class="permalink"><a href="#abb0ed2e666191dd85e543072077bf38b">&#9670;&nbsp;</a></span>m_sync_op_state_id</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname"><a class="el" href="structipc_1_1transport_1_1struc_1_1Channel_1_1Sync__op__state.html#a6b5142da7049fc212faff3914e69379b">Sync_op_state::id_t</a> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::m_sync_op_state_id</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Next unique ID for <a class="el" href="structipc_1_1transport_1_1struc_1_1Channel_1_1Sync__op__state.html#ad6f8e016b2abc3654e1915cc8c77c268" title="See id_t; used to check an arriving sync op result as belonging to the currently-waiting sync op.">Sync_op_state::m_id</a>. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01534">1534</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

</div>
</div>
<a id="a2184077da7828589d20d7f92a31a6394" name="a2184077da7828589d20d7f92a31a6394"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a2184077da7828589d20d7f92a31a6394">&#9670;&nbsp;</a></span>m_worker</h2>

<div class="memitem">
<div class="memproto">
<div class="memtemplate">
template&lt;typename Channel_obj , typename Message_body , typename Struct_builder_config , typename Struct_reader_config &gt; </div>
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">flow::async::Single_thread_task_loop <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">ipc::transport::struc::Channel</a>&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::m_worker</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Thread W used to (1) fire user-provided handlers and (2) perform any async work requested by <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aefee55a9e754a63ce52766d6c65df92c" title="The core struc::Channel engine, implementing the sync_io pattern (see util::sync_io doc header).">m_sync_io</a>. </p>

<p class="definition">Definition at line <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01543">1543</a> of file <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a>.</p>

<p class="reference">Referenced by <a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html#l01595">ipc::transport::struc::Channel&lt; Channel_obj, Message_body, Struct_builder_config, Struct_reader_config &gt;::Channel()</a>.</p>

</div>
</div>
<hr/>The documentation for this class was generated from the following files:<ul>
<li>transport/struc/<a class="el" href="ipc__transport__structured_2src_2ipc_2transport_2struc_2channel_8hpp_source.html">channel.hpp</a></li>
<li>transport/struc/<a class="el" href="struc__fwd_8hpp_source.html">struc_fwd.hpp</a></li>
</ul>
</div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Thu May 2 2024 23:56:39 for Flow-IPC by&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.4
</small></address>
</body>
</html>
